ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/package/network/utils/adb-enablemodem/Makefile b/package/network/utils/adb-enablemodem/Makefile
new file mode 100644
index 0000000..05479e3
--- /dev/null
+++ b/package/network/utils/adb-enablemodem/Makefile
@@ -0,0 +1,26 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=adb-enablemodem
+PKG_VERSION:=2017.03.05
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/adb-enablemodem
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=WWAN
+  TITLE:=Enable modem via adb
+  DEPENDS:=+adb
+endef
+
+define Build/Compile
+        true
+endef
+
+define Package/adb-enablemodem/install
+	$(INSTALL_DIR)	$(1)/etc/init.d
+	$(INSTALL_BIN)	./files/adb-enablemodem	$(1)/etc/init.d/adb-enablemodem
+endef
+
+$(eval $(call BuildPackage,adb-enablemodem))
diff --git a/package/network/utils/adb-enablemodem/files/adb-enablemodem b/package/network/utils/adb-enablemodem/files/adb-enablemodem
new file mode 100644
index 0000000..ddfc681
--- /dev/null
+++ b/package/network/utils/adb-enablemodem/files/adb-enablemodem
@@ -0,0 +1,64 @@
+#!/bin/sh /etc/rc.common
+
+START=99
+
+adb_exec() {
+	adb -s "$serial" shell "( $1 ) >/dev/null 2>&1"'; printf "\nEXIT_CODE: %i\n" $?' | head -c 64 | grep -qx 'EXIT_CODE: 0\r\?'
+}
+
+enablemodem_do() {
+	logger -t adb-enablemodem 'INFO: waiting for device'
+	adb wait-for-device
+	serial="$(adb get-serialno)"
+
+	vendor_id="$(adb -s "$serial" shell 'uci get product.usb.vid' | head -c 16 | tr -d '\r\n')"
+	product_id="$(adb -s "$serial" shell 'uci get product.usb.pid' | head -c 16 | tr -d '\r\n')"
+
+	case "$vendor_id:$product_id" in
+	"0x2357:0x000D") # TP-LINK LTE MODULE
+		case "$1" in
+		start)
+			if adb_exec '
+				chmod +x /WEBSERVER/www/cgi-bin/*
+				fds="$(ls /proc/$$/fd | grep -v "^[012]$")"
+				for fd in $fds; do
+					eval "exec $fd>&-"
+				done
+				start-stop-daemon -x httpd -S -- -h /WEBSERVER/www/
+			'; then
+				logger -t adb-enablemodem 'INFO: httpd on modem started'
+			else
+				logger -t adb-enablemodem 'ERROR: failed to start httpd on modem'
+			fi
+			option_newid='/sys/bus/usb-serial/drivers/option1/new_id'
+			if [ -e "$option_newid" ]; then
+				printf '%s %s' "$vendor_id" "$product_id" > "$option_newid"
+			fi
+			;;
+		stop)
+			if adb_exec 'start-stop-daemon -x httpd -K'; then
+				logger -t adb-enablemodem 'INFO: httpd on modem stopped'
+			else
+				logger -t adb-enablemodem 'ERROR: failed to stop httpd on modem'
+			fi
+			;;
+		esac
+		;;
+	*)
+		logger -t adb-enablemodem "ERROR: unknown device $vendor_id:$product_id"
+		;;
+	esac
+}
+
+start() {
+	( enablemodem_do start ) &
+}
+
+stop() {
+	( enablemodem_do stop ) &
+}
+
+restart() {
+	( enablemodem_do stop; enablemodem_do start ) &
+}
+
diff --git a/package/network/utils/arptables/Makefile b/package/network/utils/arptables/Makefile
new file mode 100644
index 0000000..6a92e8a
--- /dev/null
+++ b/package/network/utils/arptables/Makefile
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2006-2016 OpenWrt.org
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=arptables
+PKG_VERSION:=0.0.5
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://ftp.netfilter.org/pub/arptables
+PKG_HASH:=4f9a0656ce5c90868f551cd4deeb2d04f33899667e1fb2818b64e432fe8f629c
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/arptables
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=Firewall
+  TITLE:=ARP firewalling software
+  DEPENDS:=+kmod-arptables
+  URL:=https://git.netfilter.org/arptables/
+endef
+
+MAKE_FLAGS += \
+	COPT_FLAGS="$(TARGET_CFLAGS) -D__OPTIMIZE__=1" \
+	KERNEL_DIR="$(LINUX_DIR)"
+
+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/bpftool/Makefile b/package/network/utils/bpftool/Makefile
new file mode 100644
index 0000000..b2fdfc1
--- /dev/null
+++ b/package/network/utils/bpftool/Makefile
@@ -0,0 +1,120 @@
+#
+# Copyright (C) 2020-2024 Tony Ambardar <itugrok@yahoo.com>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bpftool
+PKG_VERSION:=7.5.0
+PKG_RELEASE:=1
+
+PKG_SOURCE_URL:=https://github.com/libbpf/bpftool
+PKG_MIRROR_HASH:=1da7c08959e7819772145774322ffd876f3180065be1c3759336dca98ac9f666
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_VERSION:=v$(PKG_VERSION)
+
+PKG_MAINTAINER:=Tony Ambardar <itugrok@yahoo.com>
+
+PKG_BUILD_FLAGS:=no-mips16 gc-sections lto
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+include $(INCLUDE_DIR)/host-build.mk
+
+define Package/bpftool/Default
+  SECTION:=net
+  CATEGORY:=Network
+  TITLE:=bpftool - eBPF subsystem utility
+  LICENSE:=GPL-2.0-only OR BSD-2-Clause
+  URL:=http://www.kernel.org
+  DEPENDS:=+libelf
+endef
+
+define Package/bpftool-minimal
+  $(call Package/bpftool/Default)
+  TITLE+= (Minimal)
+  VARIANT:=minimal
+  DEFAULT_VARIANT:=1
+  PROVIDES:=bpftool
+  ALTERNATIVES:=200:/usr/sbin/bpftool:/usr/libexec/bpftool-minimal
+endef
+
+define Package/bpftool-full
+  $(call Package/bpftool/Default)
+  TITLE+= (Full)
+  VARIANT:=full
+  PROVIDES:=bpftool
+  ALTERNATIVES:=300:/usr/sbin/bpftool:/usr/libexec/bpftool-full
+  DEPENDS+= +libbfd +libopcodes
+endef
+
+define Package/bpftool-minimal/description
+  A tool for inspection and simple manipulation of eBPF programs and maps.
+endef
+
+define Package/bpftool-full/description
+  A tool for inspection and simple manipulation of eBPF programs and maps.
+  This full version uses libbfd and libopcodes to support disassembly of
+  eBPF programs and jited code.
+endef
+
+ifeq ($(BUILD_VARIANT),full)
+  full:=1
+else
+  full:=0
+endif
+
+MAKE_FLAGS += \
+	OUTPUT="$(PKG_BUILD_DIR)/" \
+	prefix="/usr" \
+	$(if $(findstring c,$(OPENWRT_VERBOSE)),V=1,V='') \
+	check_feat=0 \
+	feature-clang-bpf-co-re=0 \
+	feature-libbfd=$(full) \
+	feature-llvm=0 \
+	feature-libcap=0 \
+	feature-disassembler-four-args=1 \
+	feature-disassembler-init-styled=1
+
+MAKE_PATH = src
+
+define Package/bpftool-$(BUILD_VARIANT)/install
+	$(INSTALL_DIR) $(1)/usr/libexec
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/bpftool \
+		$(1)/usr/libexec/bpftool-$(BUILD_VARIANT)
+endef
+
+HOST_MAKE_FLAGS += \
+	OUTPUT="$(HOST_BUILD_DIR)/" \
+	prefix="/usr" \
+	$(if $(findstring c,$(OPENWRT_VERBOSE)),V=1,V='') \
+	check_feat=0 \
+	feature-clang-bpf-co-re=0 \
+	feature-libbfd=0 \
+	feature-llvm=0 \
+	feature-libcap=0 \
+	feature-disassembler-four-args=1 \
+	feature-disassembler-init-styled=1
+
+HOST_MAKE_PATH = src
+
+define Host/Install
+	$(INSTALL_DIR) $(STAGING_DIR_HOST)/usr/sbin
+	$(INSTALL_BIN) $(HOST_BUILD_DIR)/bpftool \
+		$(STAGING_DIR_HOST)/usr/sbin/bpftool
+endef
+
+define Host/Clean
+	rm -f $(STAGING_DIR_HOST)/usr/sbin/bpftool
+endef
+
+$(eval $(call BuildPackage,bpftool-full))
+$(eval $(call BuildPackage,bpftool-minimal))
+$(eval $(call HostBuild))
diff --git a/package/network/utils/bpftool/patches/002-includes.patch b/package/network/utils/bpftool/patches/002-includes.patch
new file mode 100644
index 0000000..e6ec3f2
--- /dev/null
+++ b/package/network/utils/bpftool/patches/002-includes.patch
@@ -0,0 +1,15 @@
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -73,10 +73,10 @@ CFLAGS += -W -Wall -Wextra -Wno-unused-p
+ CFLAGS += $(filter-out -Wswitch-enum -Wnested-externs,$(EXTRA_WARNINGS))
+ CFLAGS += -DPACKAGE='"bpftool"' -D__EXPORTED_HEADERS__ \
+ 	-I$(or $(OUTPUT),.) \
+-	-I$(LIBBPF_INCLUDE) \
+ 	-I$(srctree)/src/kernel/bpf/ \
+ 	-I$(srctree)/include \
+-	-I$(srctree)/include/uapi
++	-I$(srctree)/include/uapi \
++	-I$(LIBBPF_INCLUDE)
+ ifneq ($(BPFTOOL_VERSION),)
+ CFLAGS += -DBPFTOOL_VERSION='"$(BPFTOOL_VERSION)"'
+ endif
diff --git a/package/network/utils/comgt/Makefile b/package/network/utils/comgt/Makefile
new file mode 100644
index 0000000..0e826e1
--- /dev/null
+++ b/package/network/utils/comgt/Makefile
@@ -0,0 +1,106 @@
+#
+# 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:=36
+
+PKG_SOURCE:=$(PKG_NAME).$(PKG_VERSION).tgz
+PKG_SOURCE_URL:=@SF/comgt
+PKG_HASH:=0cedb2a5aa608510da66a99aab74df3db363df495032e57e791a2ff55f1d7913
+
+PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
+PKG_LICENSE:=GPL-2.0+
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME).$(PKG_VERSION)
+PKG_CHECK_FORMAT_SECURITY:=0
+
+PKG_FLAGS:=nonshared
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/comgt/Default
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=WWAN
+endef
+
+define Package/comgt
+$(call Package/comgt/Default)
+  TITLE:=Option/Vodafone 3G/GPRS control tool
+  DEPENDS:=+chat
+  URL:=http://manpages.ubuntu.com/manpages/trusty/man1/comgt.1.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 +kmod-usb-serial-option +kmod-usb-net-huawei-cdc-ncm
+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_DATA) ./files/runcommand.gcom $(1)/etc/gcom/runcommand.gcom
+	$(INSTALL_DIR) $(1)/etc/hotplug.d/tty
+	$(INSTALL_CONF) ./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_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..42ba894
--- /dev/null
+++ b/package/network/utils/comgt/files/3g.sh
@@ -0,0 +1,118 @@
+#!/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 "delay"
+	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
+	json_get_var delay delay
+
+	[ -n "$dat_device" ] && device=$dat_device
+
+	device="$(readlink -f $device)"
+	[ -e "$device" ] || {
+		proto_set_available "$interface" 0
+		return 1
+	}
+
+	[ -n "$delay" ] && sleep "$delay"
+
+	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"
+			elif echo "$cardinfo" | grep -q "MikroTik"; then
+				COMMAND="AT+CFUN=1" gcom -d "$device" -s /etc/gcom/runcommand.gcom || return 1
+			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..9c7d07a
--- /dev/null
+++ b/package/network/utils/comgt/files/3g.usb
@@ -0,0 +1,35 @@
+#!/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
+			proto_set_available "$cfg" 1
+		fi
+		if [ "$ACTION" = remove ]; then
+			proto_set_available "$cfg" 0
+		fi
+	fi
+}
+
+[ "$ACTION" = add ] || [ "$ACTION" = remove ] || exit 0
+
+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..6535de9
--- /dev/null
+++ b/package/network/utils/comgt/files/directip.sh
@@ -0,0 +1,118 @@
+#!/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_config_add_boolean sourcefilter
+	proto_config_add_boolean delegate
+	proto_config_add_defaults
+}
+
+proto_directip_setup() {
+	local interface="$1"
+	local chat devpath devname
+
+	local device apn pincode ifname auth username password sourcefilter delegate $PROTO_DEFAULT_OPTIONS
+	json_get_vars device apn pincode auth username password sourcefilter delegate $PROTO_DEFAULT_OPTIONS
+
+	[ -n "$ctl_device" ] && device=$ctl_device
+
+	device="$(readlink -f $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
+	}
+
+	gcom -d "$device" -s /etc/gcom/getcardinfo.gcom | 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"
+	proto_add_dynamic_defaults
+	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
+	[ "$delegate" = "0" ] && json_add_boolean delegate "0"
+	[ "$sourcefilter" = "0" ] && json_add_boolean sourcefilter "0"
+	proto_add_dynamic_defaults
+	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..f91665f
--- /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 "AT+CGMI^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..5f68b13
--- /dev/null
+++ b/package/network/utils/comgt/files/ncm.json
@@ -0,0 +1,140 @@
+{
+	"huawei": {
+		"initialize": [
+			"AT",
+			"ATZ",
+			"ATQ0",
+			"ATV1",
+			"ATE1",
+			"ATS0=0",
+			"AT+CGDCONT=${profile},\\\"${pdptype}\\\"${apn:+,\\\"$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=${profile},1${apn:+,\\\"$apn\\\"}${username:+,\\\"$username\\\"}${password:+,\\\"$password\\\"}${auth:+,$auth}",
+		"disconnect": "AT^NDISDUP=${profile},0"
+	},
+	"samsung": {
+		"initialize": [
+			"AT",
+			"AT+CGREG=2",
+			"AT+CFUN=5",
+			"AT+MODESELECT=3",
+			"AT+CGDCONT=${profile},\\\"${pdptype}\\\"${apn:+,\\\"$apn\\\"}"
+		],
+		"modes": {
+			"umts": "AT+CHANGEALLPATH=1"
+		},
+		"connect": "AT+CGATT=1",
+		"disconnect": "AT+CGATT=0"
+	},
+	"sierra": {
+		"initialize": [
+			"AT+CFUN=1",
+			"AT+CGDCONT=${profile},\\\"${pdptype}\\\"${apn:+,\\\"$apn\\\"}",
+			"AT$QCPDPP=${profile},${auth:-0}${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,${profile}",
+		"disconnect": "AT!SCACT=0,${profile}"
+	},
+	"sony": {
+		"initialize": [
+			"AT+CFUN=1",
+			"AT+CGDCONT=${profile},\\\"${pdptype}\\\"${apn:+,\\\"$apn\\\"}",
+			"AT*EIAAUW=${profile},1,\\\"${username}\\\",\\\"${password}\\\",${auth:-00111}"
+		],
+		"modes": {
+			"umts": "AT+CFUN=6",
+			"gsm": "AT+CFUN=5"
+		},
+		"connect": "AT*ENAP=1,${profile}",
+		"disconnect": "AT*ENAP=0"
+	},
+	"mtk1": {
+		"initialize": [
+			"AT+CFUN=1"
+		],
+		"configure": [
+			"AT+CGDCONT=${profile},\\\"${pdptype}\\\",\\\"${apn}\\\",0,0"
+		],
+		"connect": "AT+CGACT=1,${profile}",
+		"finalize": "AT+CGDATA=\\\"M-MBIM\\\",${profile},1",
+		"disconnect": "AT+CGACT=0,${profile}"
+	},
+	"quectel": {
+		"initialize": [
+			"AT+CFUN=1"
+		],
+		"configure": [
+			"at+qicsgp=${profile},${context_type},\\\"${apn}\\\",\\\"${username}\\\",\\\"${password}\\\",0"
+		],
+		"modes": {
+			"lte": "AT+QCFG=\\\"nwscanmode\\\",3",
+			"umts": "AT+QCFG=\\\"nwscanmode\\\",2",
+			"gsm": "AT+QCFG=\\\"nwscanmode\\\",1",
+			"auto": "AT+QCFG=\\\"nwscanmode\\\",0"
+		},
+		"connect": "AT+qnetdevctl=1,${profile},1",
+		"disconnect": "AT+qnetdevctl=0,${profile},0"
+	},
+	"\"zte": {
+		"initialize": [
+			"AT+CFUN=1"
+		],
+		"configure": [
+			"AT+ZGDCONT=${profile},\\\"${pdptype}\\\",\\\"${apn}\\\",\\\"\\\",0,0",
+			"AT+ZGPCOAUTH=${profile},\\\"${username}\\\",\\\"${password}\\\",0"
+		],
+		"connect": "AT+ZGACT=1,${profile}",
+		"disconnect": "AT+ZGACT=0,${profile}"
+	},
+	"\"marvell\"": {
+		"initialize": [
+			"AT+CFUN=1"
+		],
+		"configure": [
+			"AT+ZGDCONT=${profile},\\\"${pdptype}\\\",\\\"${apn}\\\",\\\"\\\",0,0",
+			"AT+ZGPCOAUTH=${profile},\\\"${username}\\\",\\\"${password}\\\",0"
+		],
+		"connect": "AT+ZGACT=1,${profile}",
+		"disconnect": "AT+ZGACT=0,${profile}"
+	},
+	"\"mikrotik\"": {
+		"configure": [
+			"AT+CFUN=4",
+			"AT+ZGDCONT=${profile},\\\"${pdptype}\\\",\\\"${apn}\\\",0",
+			"AT+ZDHCPLEASE=10",
+			"AT+CFUN=1"
+		],
+		"waitforconnect": "\\\"+ZCONSTAT: 1,${context_type}\\\",\\\"+ZGIPDNS: ${context_type}\\\"",
+		"connect": "AT+ZGACT=1,${context_type}",
+		"finalize": "AT+ZDHCPLEASE=0",
+		"disconnect": "AT+ZGACT=0,1"
+	},
+	"spreadtrum": {
+		"initialize": [
+			"AT+CFUN=1",
+			"AT+CCED=2,8",
+			"AT+SPTTYROUTER=1"
+		],
+		"configure": [
+			"AT+CGDCONT=${profile},\\\"${pdptype}\\\"${apn:+,\\\"$apn\\\"}"
+		],
+		"connect": "AT+SPTZCMD=\\\"Y29ubm1hbmN0bCBuZGlzZGlhbCBBVF5ORElTRFVOPSJ1c2IwIiwxLDE=\\\"",
+		"disconnect": "AT+SPTZCMD=\\\"Y29ubm1hbmN0bCBuZGlzZGlhbCBBVF5ORElTRFVOPSJ1c2IwIiwwLDE=\\\""
+	}
+}
diff --git a/package/network/utils/comgt/files/ncm.sh b/package/network/utils/comgt/files/ncm.sh
new file mode 100644
index 0000000..e9412b2
--- /dev/null
+++ b/package/network/utils/comgt/files/ncm.sh
@@ -0,0 +1,289 @@
+#!/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 ifname
+	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 sourcefilter
+	proto_config_add_boolean delegate
+	proto_config_add_int profile
+	proto_config_add_defaults
+}
+
+proto_ncm_setup() {
+	local interface="$1"
+
+	local manufacturer initialize setmode connect finalize devname devpath ifpath
+
+	local device ifname  apn auth username password pincode delay mode pdptype profile $PROTO_DEFAULT_OPTIONS
+	json_get_vars device ifname apn auth username password pincode delay mode pdptype sourcefilter delegate profile $PROTO_DEFAULT_OPTIONS
+
+	local context_type
+
+	[ "$metric" = "" ] && metric="0"
+
+	[ -n "$profile" ] || profile=1
+
+	pdptype=$(echo "$pdptype" | awk '{print toupper($0)}')
+	[ "$pdptype" = "IP" -o "$pdptype" = "IPV6" -o "$pdptype" = "IPV4V6" ] || pdptype="IP"
+
+	[ "$pdptype" = "IPV4V6" ] && context_type=3
+	[ -z "$context_type" -a "$pdptype" = "IPV6" ] && context_type=2
+	[ -n "$context_type" ] || context_type=1
+
+	[ -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
+	}
+
+	device="$(readlink -f $device)"
+	[ -e "$device" ] || {
+		echo "Control device not valid"
+		proto_set_available "$interface" 0
+		return 1
+	}
+
+	[ -z "$ifname" ] && {
+		devname="$(basename "$device")"
+		case "$devname" in
+		'ttyACM'*)
+			devpath="$(readlink -f /sys/class/tty/$devname/device)"
+			ifpath="$devpath/../*/net"
+			;;
+		'tty'*)
+			devpath="$(readlink -f /sys/class/tty/$devname/device)"
+			ifpath="$devpath/../../*/net"
+			;;
+		*)
+			devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)"
+			ifpath="$devpath/net"
+			;;
+		esac
+		ifname="$(ls $(ls -1 -d $ifpath | head -n 1))"
+	}
+
+	[ -n "$ifname" ] || {
+		echo "The interface could not be found."
+		proto_notify_error "$interface" NO_IFACE
+		proto_set_available "$interface" 0
+		return 1
+	}
+
+	start=$(date +%s)
+	while true; do
+		manufacturer=$(gcom -d "$device" -s /etc/gcom/getcardinfo.gcom | awk 'NF && $0 !~ /AT\+CGMI/ { sub(/\+CGMI: /,""); print tolower($1); exit; }')
+		[ "$manufacturer" = "error" ] && {
+			manufacturer=""
+		}
+		[ -n "$manufacturer" ] && {
+			break
+		}
+		[ -z "$delay" ] && {
+			break
+		}
+		sleep 1
+		elapsed=$(($(date +%s) - start))
+		[ "$elapsed" -gt "$delay" ] && {
+			break
+		}
+	done
+	[ -z "$manufacturer" ] && {
+		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
+		}
+	}
+
+	json_get_values configure configure
+	echo "Configuring modem"
+	for i in $configure; do
+		eval COMMAND="$i" gcom -d "$device" -s /etc/gcom/runcommand.gcom || {
+			echo "Failed to configure modem"
+			proto_notify_error "$interface" CONFIGURE_FAILED
+			return 1
+		}
+	done
+
+	[ -n "$mode" ] && {
+		json_select modes
+		json_get_var setmode "$mode"
+		[ -n "$setmode" ] && {
+			echo "Setting mode"
+			eval 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 ..
+	}
+
+	echo "Starting network $interface"
+	json_get_vars connect
+	[ -n "$connect" ] && {
+		echo "Connecting modem"
+		eval COMMAND="$connect" gcom -d "$device" -s /etc/gcom/runcommand.gcom || {
+			echo "Failed to connect"
+			proto_notify_error "$interface" CONNECT_FAILED
+			return 1
+		}
+	}
+
+	json_get_vars finalize
+
+	echo "Setting up $ifname"
+	proto_init_update "$ifname" 1
+	proto_add_data
+	json_add_string "manufacturer" "$manufacturer"
+	proto_close_data
+	proto_send_update "$interface"
+
+	local zone="$(fw3 -q network "$interface" 2>/dev/null)"
+
+	[ "$pdptype" = "IP" -o "$pdptype" = "IPV4V6" ] && {
+		json_init
+		json_add_string name "${interface}_4"
+		json_add_string ifname "@$interface"
+		json_add_string proto "dhcp"
+		proto_add_dynamic_defaults
+		[ -n "$zone" ] && {
+			json_add_string zone "$zone"
+		}
+		json_close_object
+		ubus call network add_dynamic "$(json_dump)"
+	}
+
+	[ "$pdptype" = "IPV6" -o "$pdptype" = "IPV4V6" ] && {
+		json_init
+		json_add_string name "${interface}_6"
+		json_add_string ifname "@$interface"
+		json_add_string proto "dhcpv6"
+		json_add_string extendprefix 1
+		[ "$delegate" = "0" ] && json_add_boolean delegate "0"
+		[ "$sourcefilter" = "0" ] && json_add_boolean sourcefilter "0"
+		proto_add_dynamic_defaults
+		[ -n "$zone" ] && {
+			json_add_string zone "$zone"
+		}
+		json_close_object
+		ubus call network add_dynamic "$(json_dump)"
+	}
+
+	[ -n "$finalize" ] && {
+		eval COMMAND="$finalize" gcom -d "$device" -s /etc/gcom/runcommand.gcom || {
+			echo "Failed to configure modem"
+			proto_notify_error "$interface" FINALIZE_FAILED
+			return 1
+		}
+	}
+}
+
+proto_ncm_teardown() {
+	local interface="$1"
+
+	local manufacturer disconnect
+
+	local device profile
+	json_get_vars device profile
+
+	[ -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
+	}
+
+	device="$(readlink -f $device)"
+	[ -e "$device" ] || {
+		echo "Control device not valid"
+		proto_set_available "$interface" 0
+		return 1
+	}
+
+	[ -n "$profile" ] || profile=1
+
+	echo "Stopping network $interface"
+
+	json_load "$(ubus call network.interface.$interface status)"
+	json_select data
+	json_get_vars manufacturer
+	[ $? -ne 0 -o -z "$manufacturer" ] && {
+		# Fallback to direct detect, for proper handle device replug.
+		manufacturer=$(gcom -d "$device" -s /etc/gcom/getcardinfo.gcom | awk 'NF && $0 !~ /AT\+CGMI/ { sub(/\+CGMI: /,""); print tolower($1); exit; }')
+		[ $? -ne 0 -o -z "$manufacturer" ] && {
+			echo "Failed to get modem information"
+			proto_notify_error "$interface" GETINFO_FAILED
+			return 1
+		}
+		json_add_string "manufacturer" "$manufacturer"
+	}
+
+	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
+	[ -n "$disconnect" ] && {
+		eval 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..88a9d29
--- /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 25 "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..a3f3402
--- /dev/null
+++ b/package/network/utils/comgt/files/setpin.gcom
@@ -0,0 +1,56 @@
+# 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+CFUN=1^m"
+ 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/files/ussd.gcom b/package/network/utils/comgt/files/ussd.gcom
new file mode 100644
index 0000000..c5be80b
--- /dev/null
+++ b/package/network/utils/comgt/files/ussd.gcom
@@ -0,0 +1,21 @@
+opengt
+ set com 115200n81
+ set comecho off
+ set senddelay 0.02
+ waitquiet 0.2 0.2
+ flash 0.1
+
+:start
+ send "AT+CUSD=1,"
+ send $env("ussd")
+ send ",15"
+ send "^m"
+ waitfor 120 "+CUSD:"
+ if % = -1 goto timeout
+ get 1 "^m" $s
+ print $s
+ exit 0
+
+:timeout
+ print "ERROR: no USSD response, timeout.\n"
+ exit 1
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/ebtables/Makefile b/package/network/utils/ebtables/Makefile
new file mode 100644
index 0000000..49d8eff
--- /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_SOURCE_DATE:=2018-06-27
+PKG_RELEASE:=1
+
+PKG_SOURCE_URL:=https://git.netfilter.org/ebtables
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_VERSION:=48cff25dfea5b37e16ba5dc6601e98ab140f5f99
+PKG_MIRROR_HASH:=160f5087b403173d5d1e93880d28b89dab98e828ba3f545315bf1cb88afe5a46
+
+PKG_LICENSE:=GPL-2.0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ebtables
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=Firewall
+  DEPENDS:=+(!MODULE_BUILDIN):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/200-fix-extension-init.patch b/package/network/utils/ebtables/patches/200-fix-extension-init.patch
new file mode 100644
index 0000000..60e2afd
--- /dev/null
+++ b/package/network/utils/ebtables/patches/200-fix-extension-init.patch
@@ -0,0 +1,260 @@
+--- a/extensions/Makefile
++++ b/extensions/Makefile
+@@ -11,13 +11,13 @@ EXT_LIBSI+=$(foreach T,$(EXT_FUNC), -leb
+ EXT_LIBSI+=$(foreach T,$(EXT_TABLES), -lebtable_$(T))
+ 
+ extensions/ebt_%.so: extensions/ebt_%.o
+-	$(CC) $(LDFLAGS) -shared -o $@ -lc $< -nostartfiles
++	$(CC) $(LDFLAGS) -shared -o $@ -lc $<
+ 
+ extensions/libebt_%.so: extensions/ebt_%.so
+ 	mv $< $@
+ 
+ extensions/ebtable_%.so: extensions/ebtable_%.o
+-	$(CC) $(LDFLAGS) -shared -o $@ -lc $< -nostartfiles
++	$(CC) $(LDFLAGS) -shared -o $@ -lc $<
+ 
+ extensions/libebtable_%.so: extensions/ebtable_%.so
+ 	mv $< $@
+--- a/extensions/ebt_802_3.c
++++ b/extensions/ebt_802_3.c
+@@ -141,7 +141,7 @@ static struct ebt_u_match _802_3_match =
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_match(&_802_3_match);
+ }
+--- a/extensions/ebt_among.c
++++ b/extensions/ebt_among.c
+@@ -491,7 +491,7 @@ static struct ebt_u_match among_match =
+ 	.extra_ops 	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_match(&among_match);
+ }
+--- a/extensions/ebt_arp.c
++++ b/extensions/ebt_arp.c
+@@ -362,7 +362,7 @@ static struct ebt_u_match arp_match =
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_match(&arp_match);
+ }
+--- a/extensions/ebt_arpreply.c
++++ b/extensions/ebt_arpreply.c
+@@ -133,7 +133,7 @@ static struct ebt_u_target arpreply_targ
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_target(&arpreply_target);
+ }
+--- a/extensions/ebt_ip.c
++++ b/extensions/ebt_ip.c
+@@ -472,7 +472,7 @@ static struct ebt_u_match ip_match =
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_match(&ip_match);
+ }
+--- a/extensions/ebt_ip6.c
++++ b/extensions/ebt_ip6.c
+@@ -413,7 +413,7 @@ static struct ebt_u_match ip6_match =
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_match(&ip6_match);
+ }
+--- a/extensions/ebt_limit.c
++++ b/extensions/ebt_limit.c
+@@ -212,7 +212,7 @@ static struct ebt_u_match limit_match =
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_match(&limit_match);
+ }
+--- a/extensions/ebt_log.c
++++ b/extensions/ebt_log.c
+@@ -217,7 +217,7 @@ static struct ebt_u_watcher log_watcher
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_watcher(&log_watcher);
+ }
+--- a/extensions/ebt_mark.c
++++ b/extensions/ebt_mark.c
+@@ -172,7 +172,7 @@ static struct ebt_u_target mark_target =
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_target(&mark_target);
+ }
+--- a/extensions/ebt_mark_m.c
++++ b/extensions/ebt_mark_m.c
+@@ -121,7 +121,7 @@ static struct ebt_u_match mark_match =
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_match(&mark_match);
+ }
+--- a/extensions/ebt_nat.c
++++ b/extensions/ebt_nat.c
+@@ -231,7 +231,7 @@ static struct ebt_u_target dnat_target =
+ 	.extra_ops	= opts_d,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_target(&snat_target);
+ 	ebt_register_target(&dnat_target);
+--- a/extensions/ebt_nflog.c
++++ b/extensions/ebt_nflog.c
+@@ -166,7 +166,7 @@ static struct ebt_u_watcher nflog_watche
+ 	.extra_ops = nflog_opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_watcher(&nflog_watcher);
+ }
+--- a/extensions/ebt_pkttype.c
++++ b/extensions/ebt_pkttype.c
+@@ -125,7 +125,7 @@ static struct ebt_u_match pkttype_match
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_match(&pkttype_match);
+ }
+--- a/extensions/ebt_redirect.c
++++ b/extensions/ebt_redirect.c
+@@ -108,7 +108,7 @@ static struct ebt_u_target redirect_targ
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_target(&redirect_target);
+ }
+--- a/extensions/ebt_standard.c
++++ b/extensions/ebt_standard.c
+@@ -84,7 +84,7 @@ static struct ebt_u_target standard =
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_target(&standard);
+ }
+--- a/extensions/ebt_stp.c
++++ b/extensions/ebt_stp.c
+@@ -337,7 +337,7 @@ static struct ebt_u_match stp_match =
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_match(&stp_match);
+ }
+--- a/extensions/ebt_ulog.c
++++ b/extensions/ebt_ulog.c
+@@ -180,7 +180,7 @@ static struct ebt_u_watcher ulog_watcher
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_watcher(&ulog_watcher);
+ }
+--- a/extensions/ebt_vlan.c
++++ b/extensions/ebt_vlan.c
+@@ -181,7 +181,7 @@ static struct ebt_u_match vlan_match = {
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_match(&vlan_match);
+ }
+--- a/extensions/ebtable_broute.c
++++ b/extensions/ebtable_broute.c
+@@ -23,7 +23,7 @@ ebt_u_table table =
+ 	.help		= print_help,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_table(&table);
+ }
+--- a/extensions/ebtable_filter.c
++++ b/extensions/ebtable_filter.c
+@@ -29,7 +29,7 @@ static struct ebt_u_table table =
+ 	.help		= print_help,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_table(&table);
+ }
+--- a/extensions/ebtable_nat.c
++++ b/extensions/ebtable_nat.c
+@@ -30,7 +30,7 @@ ebt_u_table table =
+ 	.help		= print_help,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_table(&table);
+ }
+--- a/extensions/ebt_string.c
++++ b/extensions/ebt_string.c
+@@ -312,7 +312,7 @@ static struct ebt_u_match string_match =
+ 	.extra_ops	= opts,
+ };
+ 
+-void _init(void)
++__attribute__((constructor)) static void extension_init(void)
+ {
+ 	ebt_register_match(&string_match);
+ }
diff --git a/package/network/utils/ethtool/Makefile b/package/network/utils/ethtool/Makefile
new file mode 100644
index 0000000..5da6527
--- /dev/null
+++ b/package/network/utils/ethtool/Makefile
@@ -0,0 +1,73 @@
+#
+# 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:=ethtool
+PKG_VERSION:=6.11
+PKG_RELEASE:=1
+
+PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/software/network/ethtool
+PKG_HASH:=8d91f5c72ae3f25b7e88d4781279dcb320f71e30058914370b1c574c96b31202
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:kernel:ethtool
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ethtool
+  SECTION:=net
+  CATEGORY:=Network
+  TITLE:=Display or change ethernet card settings
+  URL:=http://www.kernel.org/pub/software/network/ethtool/
+  VARIANT:=tiny
+  CONFLICTS:=ethtool-full
+endef
+
+define Package/ethtool-full
+  $(Package/ethtool)
+  TITLE += (full)
+  VARIANT:=full
+  PROVIDES:=ethtool
+  DEPENDS:=+libmnl
+  CONFLICTS:=
+endef
+
+define Package/ethtool/description
+ ethtool is a small utility for examining and tuning your ethernet-based
+ network interface
+endef
+
+Package/ethtool-full/description:=$(Package/ethtool/description)
+
+ifeq ($(BUILD_VARIANT),full)
+CONFIGURE_ARGS += --enable-netlink --enable-pretty-dump
+else
+CONFIGURE_ARGS += --disable-netlink --disable-pretty-dump
+endif
+
+# enable support for input_xfrm with kernels newer than 6.6
+ifeq ($(CONFIG_LINUX_6_6),)
+CONFIGURE_ARGS += --enable-rss-input-xfrm
+endif
+
+define Package/ethtool/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/ethtool $(1)/usr/sbin
+endef
+
+Package/ethtool-full/install=$(Package/ethtool/install)
+
+$(eval $(call BuildPackage,ethtool))
+$(eval $(call BuildPackage,ethtool-full))
diff --git a/package/network/utils/ethtool/patches/0001-ethtool-make-building-for-RSS-input-xfrm-optional.patch b/package/network/utils/ethtool/patches/0001-ethtool-make-building-for-RSS-input-xfrm-optional.patch
new file mode 100644
index 0000000..4c8403d
--- /dev/null
+++ b/package/network/utils/ethtool/patches/0001-ethtool-make-building-for-RSS-input-xfrm-optional.patch
@@ -0,0 +1,67 @@
+From c88eb6f4e9b2d8f71f3391db2bf0ec82ecccae81 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Wed, 12 Feb 2025 04:12:42 +0000
+Subject: [PATCH] ethtool: make building for RSS input xfrm optional
+
+Unfortunately there is no way to detect at runtime if the kernel the
+support for RSS input transformation, and the default value
+RXH_XFRM_NO_CHANGE (0xff) used by newer ethtool results in breakage
+with older kernels.
+As a stop-gap solution simply don't compile with support for input
+xfrm by default.
+
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+---
+ configure.ac | 10 ++++++++++
+ ethtool.c    | 10 ++++++++++
+ 2 files changed, 20 insertions(+)
+
+--- a/configure.ac
++++ b/configure.ac
+@@ -45,6 +45,16 @@ if test x$enable_pretty_dump = xyes; the
+ fi
+ AM_CONDITIONAL([ETHTOOL_ENABLE_PRETTY_DUMP], [test x$enable_pretty_dump = xyes])
+ 
++AC_ARG_ENABLE(rss-input-xfrm,
++	      [  --enable-rss-input-xfrm  build with support for RSS input transformation (disabled by default)],
++	      ,
++	      enable_rss_input_xfrm=no)
++if test x$enable_rss_input_xfrm = xyes; then
++    AC_DEFINE(ETHTOOL_ENABLE_RSS_INPUT_XFRM, 1,
++	      [Define this to enable building with support for RSS input transformation.])
++fi
++AM_CONDITIONAL([ETHTOOL_ENABLE_RSS_INPUT_XFRM], [test x$enable_rss_input_xfrm = xyes])
++
+ AC_ARG_WITH([bash-completion-dir],
+ 	    AS_HELP_STRING([--with-bash-completion-dir[=PATH]],
+ 	                   [Install the bash-completion script in this directory. @<:@default=yes@:>@]),
+--- a/ethtool.c
++++ b/ethtool.c
+@@ -4109,9 +4109,11 @@ static int do_grxfh(struct cmd_context *
+ 		       (const char *)hfuncs->data + i * ETH_GSTRING_LEN,
+ 		       (rss->hfunc & (1 << i)) ? "on" : "off");
+ 
++#ifdef ETHTOOL_ENABLE_RSS_INPUT_XFRM
+ 	printf("RSS input transformation:\n");
+ 	printf("    symmetric-xor: %s\n",
+ 	       (rss->input_xfrm & RXH_XFRM_SYM_XOR) ? "on" : "off");
++#endif
+ 
+ out:
+ 	free(hfuncs);
+@@ -4431,7 +4433,15 @@ static int do_srxfh(struct cmd_context *
+ 	rss->cmd = ETHTOOL_SRSSH;
+ 	rss->rss_context = rss_context;
+ 	rss->hfunc = req_hfunc;
++#ifdef ETHTOOL_ENABLE_RSS_INPUT_XFRM
+ 	rss->input_xfrm = req_input_xfrm;
++#else
++	if (req_input_xfrm != 0xff) {
++		perror("Compiled for kernel without support for input transformation");
++		err = 1;
++		goto free;
++	}
++#endif
+ 	if (delete) {
+ 		rss->indir_size = rss->key_size = 0;
+ 	} else {
diff --git a/package/network/utils/iproute2/Makefile b/package/network/utils/iproute2/Makefile
new file mode 100644
index 0000000..04a4df2
--- /dev/null
+++ b/package/network/utils/iproute2/Makefile
@@ -0,0 +1,268 @@
+#
+# 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:=6.11.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/linux/utils/net/iproute2
+PKG_HASH:=1f795398a04aeaacd06a8f6ace2cfd913c33fa5953ca99daae83bb5c534611c3
+PKG_BUILD_PARALLEL:=1
+PKG_BUILD_DEPENDS:=iptables
+PKG_LICENSE:=GPL-2.0
+PKG_CPE_ID:=cpe:/a:iproute2_project:iproute2
+
+PKG_BUILD_FLAGS:=gc-sections lto
+
+include $(INCLUDE_DIR)/kernel.mk
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/iproute2/Default
+  SECTION:=net
+  CATEGORY:=Network
+  URL:=http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2
+  SUBMENU:=Routing and Redirection
+  MAINTAINER:=Russell Senior <russell@personaltelco.net>
+endef
+
+define Package/ip-tiny
+$(call Package/iproute2/Default)
+  TITLE:=Routing control utility (minimal)
+  VARIANT:=iptiny
+  DEFAULT_VARIANT:=1
+  PROVIDES:=ip
+  ALTERNATIVES:=200:/sbin/ip:/usr/libexec/ip-tiny
+  DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl
+endef
+
+define Package/ip-full
+$(call Package/iproute2/Default)
+  TITLE:=Routing control utility (full)
+  VARIANT:=ipfull
+  PROVIDES:=ip
+  ALTERNATIVES:=300:/sbin/ip:/usr/libexec/ip-full
+  DEPENDS:=+libnl-tiny +libbpf +(PACKAGE_devlink||PACKAGE_rdma):libmnl
+endef
+
+define Package/tc-tiny
+$(call Package/iproute2/Default)
+  TITLE:=Traffic control utility (minimal)
+  VARIANT:=tctiny
+  DEFAULT_VARIANT:=1
+  PROVIDES:=tc
+  ALTERNATIVES:=200:/sbin/tc:/usr/libexec/tc-tiny
+  DEPENDS:=+kmod-sched-core +(PACKAGE_devlink||PACKAGE_rdma):libmnl
+endef
+
+define Package/tc-bpf
+$(call Package/iproute2/Default)
+  TITLE:=Traffic control utility (bpf)
+  VARIANT:=tcbpf
+  PROVIDES:=tc
+  ALTERNATIVES:=300:/sbin/tc:/usr/libexec/tc-bpf
+  DEPENDS:=+kmod-sched-core +(PACKAGE_devlink||PACKAGE_rdma):libmnl +libbpf
+endef
+
+define Package/tc-full
+$(call Package/iproute2/Default)
+  TITLE:=Traffic control utility (full)
+  VARIANT:=tcfull
+  PROVIDES:=tc
+  ALTERNATIVES:=400:/sbin/tc:/usr/libexec/tc-full
+  DEPENDS:=+kmod-sched-core +(PACKAGE_devlink||PACKAGE_rdma):libmnl +libbpf +libxtables
+endef
+
+define Package/genl
+$(call Package/iproute2/Default)
+  TITLE:=General netlink utility frontend
+  DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl
+endef
+
+define Package/ip-bridge
+$(call Package/iproute2/Default)
+  TITLE:=Bridge configuration utility from iproute2
+  DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl
+endef
+
+define Package/ss
+$(call Package/iproute2/Default)
+  TITLE:=Socket statistics utility
+  DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl +libbpf +kmod-netlink-diag
+endef
+
+define Package/nstat
+$(call Package/iproute2/Default)
+  TITLE:=Network statistics utility
+  DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl
+endef
+
+define Package/devlink
+$(call Package/iproute2/Default)
+  TITLE:=Network devlink utility
+  DEPENDS:=+libmnl
+endef
+
+define Package/rdma
+$(call Package/iproute2/Default)
+  TITLE:=Network rdma utility
+  DEPENDS:=+libmnl
+endef
+
+ifeq ($(BUILD_VARIANT),iptiny)
+  IP_CONFIG_TINY:=y
+  LIBBPF_FORCE:=off
+endif
+
+ifeq ($(BUILD_VARIANT),ipfull)
+  HAVE_ELF:=y
+  LIBBPF_FORCE:=on
+endif
+
+ifeq ($(BUILD_VARIANT),tctiny)
+  LIBBPF_FORCE:=off
+endif
+
+ifeq ($(BUILD_VARIANT),tcbpf)
+  HAVE_ELF:=y
+  LIBBPF_FORCE:=on
+  SHARED_LIBS:=y
+endif
+
+ifeq ($(BUILD_VARIANT),tcfull)
+  #enable iptables/xtables requirement only if tciptables variant is selected
+  TC_CONFIG_XT:=y
+  TC_CONFIG_XT_OLD:=y
+  TC_CONFIG_XT_OLD_H:=y
+  TC_CONFIG_IPSET:=y
+  HAVE_ELF:=y
+  LIBBPF_FORCE:=on
+  SHARED_LIBS:=y
+else
+  #disable iptables requirement by default
+  TC_CONFIG_XT:=n
+  TC_CONFIG_XT_OLD:=n
+  TC_CONFIG_XT_OLD_H:=n
+  TC_CONFIG_IPSET:=n
+endif
+
+ifdef CONFIG_PACKAGE_devlink
+  HAVE_MNL:=y
+endif
+
+ifdef CONFIG_PACKAGE_rdma
+  HAVE_MNL:=y
+endif
+
+define Build/Configure
+	echo "static const char SNAPSHOT[] = \"$(PKG_VERSION)-$(PKG_RELEASE)-openwrt\";" \
+		> $(PKG_BUILD_DIR)/include/SNAPSHOT.h
+endef
+
+TARGET_LDFLAGS += -Wl,--as-needed
+TARGET_CPPFLAGS += -I$(STAGING_DIR)/usr/include/libnl-tiny
+
+MAKE_FLAGS += \
+	KERNEL_INCLUDE="$(LINUX_DIR)/include/uapi" \
+	SHARED_LIBS=$(SHARED_LIBS) \
+	IP_CONFIG_TINY=$(IP_CONFIG_TINY) \
+	BUILD_VARIANT=$(BUILD_VARIANT) \
+	LIBBPF_FORCE=$(LIBBPF_FORCE) \
+	HAVE_ELF=$(HAVE_ELF) \
+	HAVE_MNL=$(HAVE_MNL) \
+	HAVE_CAP=$(HAVE_CAP) \
+	HAVE_TIRPC=n \
+	IPT_LIB_DIR=/usr/lib/iptables \
+	XT_LIB_DIR=/usr/lib/iptables \
+	TC_CONFIG_XT=$(TC_CONFIG_XT) \
+	TC_CONFIG_XT_OLD=$(TC_CONFIG_XT_OLD) \
+	TC_CONFIG_XT_OLD_H=$(TC_CONFIG_XT_OLD_H) \
+	TC_CONFIG_IPSET=$(TC_CONFIG_IPSET) \
+	FPIC="$(FPIC)" \
+	$(if $(findstring c,$(OPENWRT_VERBOSE)),V=1,V='')
+
+define Build/Compile
+	+$(MAKE_VARS) $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS)
+endef
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(1)/usr/include/iproute2
+	$(CP) $(PKG_BUILD_DIR)/include/bpf_elf.h $(1)/usr/include/iproute2
+	$(CP) $(PKG_BUILD_DIR)/include/{libgenl,libnetlink}.h $(1)/usr/include/
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_BUILD_DIR)/lib/libnetlink.a $(1)/usr/lib/
+endef
+
+define Package/ip-tiny/install
+	$(INSTALL_DIR) $(1)/usr/libexec
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/ip/ip $(1)/usr/libexec/ip-tiny
+endef
+
+define Package/ip-full/install
+	$(INSTALL_DIR) $(1)/usr/libexec
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/ip/ip $(1)/usr/libexec/ip-full
+endef
+
+define Package/tc-tiny/install
+	$(INSTALL_DIR) $(1)/usr/libexec
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/tc/tc $(1)/usr/libexec/tc-tiny
+endef
+
+define Package/tc-bpf/install
+	$(INSTALL_DIR) $(1)/usr/libexec
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/tc/tc $(1)/usr/libexec/tc-bpf
+endef
+
+define Package/tc-full/install
+	$(INSTALL_DIR) $(1)/usr/libexec
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/tc/tc $(1)/usr/libexec/tc-full
+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
+
+define Package/nstat/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/misc/nstat $(1)/usr/sbin/
+endef
+
+define Package/devlink/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/devlink/devlink $(1)/usr/sbin/
+endef
+
+define Package/rdma/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/rdma/rdma $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,ip-tiny))
+$(eval $(call BuildPackage,ip-full))
+$(eval $(call BuildPackage,tc-tiny))
+$(eval $(call BuildPackage,tc-bpf))
+$(eval $(call BuildPackage,tc-full))
+$(eval $(call BuildPackage,genl))
+$(eval $(call BuildPackage,ip-bridge))
+$(eval $(call BuildPackage,ss))
+$(eval $(call BuildPackage,nstat))
+$(eval $(call BuildPackage,devlink))
+$(eval $(call BuildPackage,rdma))
diff --git a/package/network/utils/iproute2/patches/010-bridge-mst-fix-a-musl-build-issue.patch b/package/network/utils/iproute2/patches/010-bridge-mst-fix-a-musl-build-issue.patch
new file mode 100644
index 0000000..1630415
--- /dev/null
+++ b/package/network/utils/iproute2/patches/010-bridge-mst-fix-a-musl-build-issue.patch
@@ -0,0 +1,68 @@
+From 6a77abab92516e65f07f8657fc4e384c4541ce0e Mon Sep 17 00:00:00 2001
+From: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+Date: Sun, 22 Sep 2024 16:50:10 +0200
+Subject: bridge: mst: fix a musl build issue
+
+This patch fixes a compilation error raised by the bump to version 6.11.0
+in Buildroot using musl as the C library for the cross-compilation
+toolchain.
+
+After setting the CFLGAS
+
+ifeq ($(BR2_TOOLCHAIN_USES_MUSL),y)
+IPROUTE2_CFLAGS += -D__UAPI_DEF_IN6_ADDR=0 -D__UAPI_DEF_SOCKADDR_IN6=0 \
+			-D__UAPI_DEF_IPV6_MREQ=0
+endif
+
+to fix the following errors:
+
+In file included from ../../../host/mips64-buildroot-linux-musl/sysroot/usr/include/arpa/inet.h:9,
+                 from ../include/libnetlink.h:14,
+                 from mst.c:10:
+../../../host/mips64-buildroot-linux-musl/sysroot/usr/include/netinet/in.h:23:8: error: redefinition of 'struct in6_addr'
+   23 | struct in6_addr {
+      |        ^~~~~~~~
+In file included from ../include/uapi/linux/if_bridge.h:19,
+                 from mst.c:7:
+../include/uapi/linux/in6.h:33:8: note: originally defined here
+   33 | struct in6_addr {
+      |        ^~~~~~~~
+../../../host/mips64-buildroot-linux-musl/sysroot/usr/include/netinet/in.h:34:8: error: redefinition of 'struct sockaddr_in6'
+   34 | struct sockaddr_in6 {
+      |        ^~~~~~~~~~~~
+../include/uapi/linux/in6.h:50:8: note: originally defined here
+   50 | struct sockaddr_in6 {
+      |        ^~~~~~~~~~~~
+../../../host/mips64-buildroot-linux-musl/sysroot/usr/include/netinet/in.h:42:8: error: redefinition of 'struct ipv6_mreq'
+   42 | struct ipv6_mreq {
+      |        ^~~~~~~~~
+../include/uapi/linux/in6.h:60:8: note: originally defined here
+   60 | struct ipv6_mreq {
+
+I got this further errors
+
+../include/uapi/linux/in6.h:72:25: error: field 'flr_dst' has incomplete type
+   72 |         struct in6_addr flr_dst;
+      |                         ^~~~~~~
+../include/uapi/linux/if_bridge.h:711:41: error: field 'ip6' has incomplete type
+  711 |                         struct in6_addr ip6;
+      |                                         ^~~
+
+fixed by including the netinet/in.h header.
+
+Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
+---
+ bridge/mst.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/bridge/mst.c
++++ b/bridge/mst.c
+@@ -4,6 +4,7 @@
+  */
+ 
+ #include <stdio.h>
++#include <netinet/in.h>
+ #include <linux/if_bridge.h>
+ #include <net/if.h>
+ 
diff --git a/package/network/utils/iproute2/patches/011-bridge-mst-fix-a-further-musl-build-issue.patch b/package/network/utils/iproute2/patches/011-bridge-mst-fix-a-further-musl-build-issue.patch
new file mode 100644
index 0000000..1bdab39
--- /dev/null
+++ b/package/network/utils/iproute2/patches/011-bridge-mst-fix-a-further-musl-build-issue.patch
@@ -0,0 +1,51 @@
+From 043ef90e2fa94397eb5c85330889ca4146a6d58a Mon Sep 17 00:00:00 2001
+From: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+Date: Sun, 22 Sep 2024 16:50:11 +0200
+Subject: bridge: mst: fix a further musl build issue
+
+This patch fixes the following build errors:
+
+In file included from mst.c:11:
+../include/json_print.h:80:30: warning: 'struct timeval' declared inside parameter list will not be visible outside of this definition or declaration
+   80 | _PRINT_FUNC(tv, const struct timeval *)
+      |                              ^~~~~~~
+../include/json_print.h:50:37: note: in definition of macro '_PRINT_FUNC'
+   50 |                                     type value);                        \
+      |                                     ^~~~
+../include/json_print.h:80:30: warning: 'struct timeval' declared inside parameter list will not be visible outside of this definition or declaration
+   80 | _PRINT_FUNC(tv, const struct timeval *)
+      |                              ^~~~~~~
+../include/json_print.h:55:45: note: in definition of macro '_PRINT_FUNC'
+   55 |                                             type value)                 \
+      |                                             ^~~~
+../include/json_print.h: In function 'print_tv':
+../include/json_print.h:58:48: error: passing argument 5 of 'print_color_tv' from incompatible pointer type [-Wincompatible-pointer-types]
+   58 |                                                value);                  \
+      |                                                ^~~~~
+      |                                                |
+      |                                                const struct timeval *
+../include/json_print.h:80:1: note: in expansion of macro '_PRINT_FUNC'
+   80 | _PRINT_FUNC(tv, const struct timeval *)
+      | ^~~~~~~~~~~
+../include/json_print.h:50:42: note: expected 'const struct timeval *' but argument is of type 'const struct timeval *'
+   50 |                                     type value);                        \
+      |                                          ^
+../include/json_print.h:80:1: note: in expansion of macro '_PRINT_FUNC'
+   80 | _PRINT_FUNC(tv, const struct timeval *)
+
+Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
+---
+ bridge/mst.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/bridge/mst.c
++++ b/bridge/mst.c
+@@ -4,6 +4,7 @@
+  */
+ 
+ #include <stdio.h>
++#include <sys/time.h>
+ #include <netinet/in.h>
+ #include <linux/if_bridge.h>
+ #include <net/if.h>
diff --git a/package/network/utils/iproute2/patches/012-libnetlink-fix-build-with-musl-and-gcc-14.patch b/package/network/utils/iproute2/patches/012-libnetlink-fix-build-with-musl-and-gcc-14.patch
new file mode 100644
index 0000000..749176a
--- /dev/null
+++ b/package/network/utils/iproute2/patches/012-libnetlink-fix-build-with-musl-and-gcc-14.patch
@@ -0,0 +1,28 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Thu, 8 Aug 2024 09:19:01 +0200
+Subject: libnetlink: fix build with musl and gcc 14
+
+Fixes compilation error with musl libc and gcc 14:
+
+../include/libnetlink.h: In function 'rta_getattr_be64':
+../include/libnetlink.h:280:16: error: implicit declaration of function 'htobe64' [-Wimplicit-function-declaration]
+  280 |         return htobe64(rta_getattr_u64(rta));
+      |                ^~~~~~~
+
+Reference: https://man7.org/linux/man-pages/man3/endian.3.html
+Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
+---
+ include/libnetlink.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/include/libnetlink.h
++++ b/include/libnetlink.h
+@@ -2,6 +2,7 @@
+ #ifndef __LIBNETLINK_H__
+ #define __LIBNETLINK_H__ 1
+ 
++#include <endian.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <asm/types.h>
diff --git a/package/network/utils/iproute2/patches/110-darwin_fixes.patch b/package/network/utils/iproute2/patches/110-darwin_fixes.patch
new file mode 100644
index 0000000..06ae59f
--- /dev/null
+++ b/package/network/utils/iproute2/patches/110-darwin_fixes.patch
@@ -0,0 +1,59 @@
+--- a/netem/maketable.c
++++ b/netem/maketable.c
+@@ -11,7 +11,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
+@@ -9,8 +9,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
+@@ -8,8 +8,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/115-add-config-xtlibdir.patch b/package/network/utils/iproute2/patches/115-add-config-xtlibdir.patch
new file mode 100644
index 0000000..38448e6
--- /dev/null
+++ b/package/network/utils/iproute2/patches/115-add-config-xtlibdir.patch
@@ -0,0 +1,12 @@
+--- a/tc/Makefile
++++ b/tc/Makefile
+@@ -107,6 +107,9 @@ CFLAGS += -DCONFIG_GACT -DCONFIG_GACT_PR
+ ifneq ($(IPT_LIB_DIR),)
+ 	CFLAGS += -DIPT_LIB_DIR=\"$(IPT_LIB_DIR)\"
+ endif
++ifneq ($(XT_LIB_DIR),)
++	CFLAGS += -DXT_LIB_DIR=\"$(XT_LIB_DIR)\"
++endif
+ 
+ LEX := flex
+ CFLAGS += -DYY_NO_INPUT
diff --git a/package/network/utils/iproute2/patches/120-no_arpd_ifstat_rtacct_lnstat.patch b/package/network/utils/iproute2/patches/120-no_arpd_ifstat_rtacct_lnstat.patch
new file mode 100644
index 0000000..bb6a8d0
--- /dev/null
+++ b/package/network/utils/iproute2/patches/120-no_arpd_ifstat_rtacct_lnstat.patch
@@ -0,0 +1,20 @@
+--- a/misc/Makefile
++++ b/misc/Makefile
+@@ -2,13 +2,13 @@
+ SSOBJ=ss.o ssfilter_check.o ssfilter.tab.o
+ LNSTATOBJ=lnstat.o lnstat_util.o
+ 
+-TARGETS=ss nstat ifstat rtacct lnstat
++TARGETS=ss nstat
+ 
+ include ../config.mk
+ 
+-ifeq ($(HAVE_BERKELEY_DB),y)
+-	TARGETS += arpd
+-endif
++#ifeq ($(HAVE_BERKELEY_DB),y)
++#	TARGETS += arpd
++#endif
+ 
+ all: $(TARGETS)
+ 
diff --git a/package/network/utils/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch b/package/network/utils/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch
new file mode 100644
index 0000000..7f94607
--- /dev/null
+++ b/package/network/utils/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch
@@ -0,0 +1,14 @@
+--- a/Makefile
++++ b/Makefile
+@@ -69,9 +69,9 @@ WFLAGS += -Wmissing-declarations -Wold-s
+ CFLAGS := $(WFLAGS) $(CCOPTS) -I../include -I../include/uapi $(DEFINES) $(CFLAGS)
+ YACCFLAGS = -d -t -v
+ 
+-SUBDIRS=lib ip tc bridge misc netem genl man
++SUBDIRS=lib ip tc bridge misc genl
+ ifeq ($(HAVE_MNL),y)
+-SUBDIRS += tipc devlink rdma dcb vdpa
++SUBDIRS += devlink rdma
+ endif
+ 
+ LIBNETLINK=../lib/libutil.a ../lib/libnetlink.a
diff --git a/package/network/utils/iproute2/patches/140-allow_pfifo_fast.patch b/package/network/utils/iproute2/patches/140-allow_pfifo_fast.patch
new file mode 100644
index 0000000..8f5a7d3
--- /dev/null
+++ b/package/network/utils/iproute2/patches/140-allow_pfifo_fast.patch
@@ -0,0 +1,9 @@
+--- a/tc/q_fifo.c
++++ b/tc/q_fifo.c
+@@ -90,5 +90,6 @@ struct qdisc_util pfifo_head_drop_qdisc_
+ 
+ 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/140-keep_libmnl_optional.patch b/package/network/utils/iproute2/patches/140-keep_libmnl_optional.patch
new file mode 100644
index 0000000..48a4ae7
--- /dev/null
+++ b/package/network/utils/iproute2/patches/140-keep_libmnl_optional.patch
@@ -0,0 +1,11 @@
+--- a/configure
++++ b/configure
+@@ -368,7 +368,7 @@ check_tirpc()
+ 
+ check_mnl()
+ {
+-	if ${PKG_CONFIG} libmnl --exists; then
++	if [ "${HAVE_MNL}" = "y" ] && ${PKG_CONFIG} libmnl --exists; then
+ 		echo "HAVE_MNL:=y" >>$CONFIG
+ 		echo "yes"
+ 
diff --git a/package/network/utils/iproute2/patches/145-keep_libelf_optional.patch b/package/network/utils/iproute2/patches/145-keep_libelf_optional.patch
new file mode 100644
index 0000000..99b9d32
--- /dev/null
+++ b/package/network/utils/iproute2/patches/145-keep_libelf_optional.patch
@@ -0,0 +1,11 @@
+--- a/configure
++++ b/configure
+@@ -217,7 +217,7 @@ EOF
+ 
+ check_elf()
+ {
+-    if ${PKG_CONFIG} libelf --exists; then
++    if [ "${HAVE_ELF}" = "y" ] && ${PKG_CONFIG} libelf --exists; then
+ 	echo "HAVE_ELF:=y" >>$CONFIG
+ 	echo "yes"
+ 
diff --git a/package/network/utils/iproute2/patches/150-keep_libcap_optional.patch b/package/network/utils/iproute2/patches/150-keep_libcap_optional.patch
new file mode 100644
index 0000000..49873f8
--- /dev/null
+++ b/package/network/utils/iproute2/patches/150-keep_libcap_optional.patch
@@ -0,0 +1,11 @@
+--- a/configure
++++ b/configure
+@@ -427,7 +427,7 @@ EOF
+ 
+ check_cap()
+ {
+-	if ${PKG_CONFIG} libcap --exists; then
++	if [ "${HAVE_CAP}" = "y" ] && ${PKG_CONFIG} libcap --exists; then
+ 		echo "HAVE_CAP:=y" >>$CONFIG
+ 		echo "yes"
+ 
diff --git a/package/network/utils/iproute2/patches/155-keep_tirpc_optional.patch b/package/network/utils/iproute2/patches/155-keep_tirpc_optional.patch
new file mode 100644
index 0000000..9e5e433
--- /dev/null
+++ b/package/network/utils/iproute2/patches/155-keep_tirpc_optional.patch
@@ -0,0 +1,11 @@
+--- a/configure
++++ b/configure
+@@ -355,7 +355,7 @@ check_selinux()
+ 
+ check_tirpc()
+ {
+-	if ${PKG_CONFIG} libtirpc --exists; then
++	if [ "${HAVE_TIRPC}" = "y" ] && ${PKG_CONFIG} libtirpc --exists; then
+ 		echo "HAVE_RPC:=y" >>$CONFIG
+ 		echo "yes"
+ 
diff --git a/package/network/utils/iproute2/patches/160-libnetlink-pic.patch b/package/network/utils/iproute2/patches/160-libnetlink-pic.patch
new file mode 100644
index 0000000..145ec7a
--- /dev/null
+++ b/package/network/utils/iproute2/patches/160-libnetlink-pic.patch
@@ -0,0 +1,11 @@
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ include ../config.mk
+ 
+-CFLAGS += -fPIC
++CFLAGS += $(FPIC)
+ 
+ UTILOBJ = utils.o utils_math.o rt_names.o ll_map.o ll_types.o ll_proto.o ll_addr.o \
+ 	inet_proto.o namespace.o json_writer.o json_print.o json_print_math.o \
diff --git a/package/network/utils/iproute2/patches/170-ip_tiny.patch b/package/network/utils/iproute2/patches/170-ip_tiny.patch
new file mode 100644
index 0000000..149bcd2
--- /dev/null
+++ b/package/network/utils/iproute2/patches/170-ip_tiny.patch
@@ -0,0 +1,108 @@
+--- a/ip/Makefile
++++ b/ip/Makefile
+@@ -19,6 +19,13 @@ RTMONOBJ=rtmon.o
+ 
+ include ../config.mk
+ 
++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=routel
+ TARGETS=ip rtmon
+@@ -48,7 +55,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
+@@ -61,11 +61,17 @@ static void usage(void)
+ 	fprintf(stderr,
+ 		"Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n"
+ 		"       ip [ -force ] -batch filename\n"
++#ifndef IPROUTE2_TINY
+ 		"where  OBJECT := { address | addrlabel | fou | help | ila | ioam | l2tp | link |\n"
+ 		"                   macsec | maddress | monitor | mptcp | mroute | mrule |\n"
+ 		"                   neighbor | neighbour | netconf | netns | nexthop | ntable |\n"
+ 		"                   ntbl | route | rule | sr | stats | tap | tcpmetrics |\n"
+ 		"                   token | tunnel | tuntap | vrf | xfrm }\n"
++#else
++		"where  OBJECT := { address | help | link | maddress | monitor |\n"
++		"                   neighbor | neighbour | netns | route |\n"
++		"                   rule | stats | token | tunnel }\n"
++#endif
+ 		"       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
+ 		"                    -h[uman-readable] | -iec | -j[son] | -p[retty] |\n"
+ 		"                    -f[amily] { inet | inet6 | mpls | bridge | link } |\n"
+@@ -88,37 +94,49 @@ 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 },
+ 	{ "ila",	do_ipila },
+ 	{ "macsec",	do_ipmacsec },
++#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 },
+ 	{ "mroute",	do_multiroute },
+ 	{ "mrule",	do_multirule },
++#endif
+ 	{ "netns",	do_netns },
++#ifndef IPROUTE2_TINY
+ 	{ "netconf",	do_ipnetconf },
+ 	{ "vrf",	do_ipvrf},
+ 	{ "sr",		do_seg6 },
+ 	{ "nexthop",	do_ipnh },
+ 	{ "mptcp",	do_mptcp },
+ 	{ "ioam",	do_ioam6 },
++#endif
+ 	{ "help",	do_help },
+ 	{ "stats",	do_ipstats },
+ 	{ 0 }
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -3,6 +3,10 @@ include ../config.mk
+ 
+ CFLAGS += $(FPIC)
+ 
++ifeq ($(IP_CONFIG_TINY),y)
++  CFLAGS += -DIPROUTE2_TINY
++endif
++
+ UTILOBJ = utils.o utils_math.o rt_names.o ll_map.o ll_types.o ll_proto.o ll_addr.o \
+ 	inet_proto.o namespace.o json_writer.o json_print.o json_print_math.o \
+ 	names.o color.o bpf_legacy.o bpf_glue.o exec.o fs.o cg_map.o ppp_proto.o
diff --git a/package/network/utils/iproute2/patches/180-drop_FAILED_POLICY.patch b/package/network/utils/iproute2/patches/180-drop_FAILED_POLICY.patch
new file mode 100644
index 0000000..9ce7dd9
--- /dev/null
+++ b/package/network/utils/iproute2/patches/180-drop_FAILED_POLICY.patch
@@ -0,0 +1,41 @@
+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/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)
+--- a/include/uapi/linux/rtnetlink.h
++++ b/include/uapi/linux/rtnetlink.h
+@@ -265,6 +265,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
+ };
+ 
diff --git a/package/network/utils/iproute2/patches/190-fix-nls-rpath-link.patch b/package/network/utils/iproute2/patches/190-fix-nls-rpath-link.patch
new file mode 100644
index 0000000..545075f
--- /dev/null
+++ b/package/network/utils/iproute2/patches/190-fix-nls-rpath-link.patch
@@ -0,0 +1,20 @@
+--- a/configure
++++ b/configure
+@@ -241,7 +241,7 @@ int main(int argc, char **argv) {
+ }
+ EOF
+ 
+-    $CC -o $TMPDIR/libbpf_test $TMPDIR/libbpf_test.c $LIBBPF_CFLAGS $LIBBPF_LDLIBS >/dev/null 2>&1
++    $CC -o $TMPDIR/libbpf_test $TMPDIR/libbpf_test.c $LIBBPF_CFLAGS $LIBBPF_LDLIBS $LDFLAGS >/dev/null 2>&1
+     local ret=$?
+ 
+     rm -f $TMPDIR/libbpf_test.c $TMPDIR/libbpf_test
+@@ -259,7 +259,7 @@ int main(int argc, char **argv) {
+ }
+ EOF
+ 
+-    $CC -o $TMPDIR/libbpf_sec_test $TMPDIR/libbpf_sec_test.c $LIBBPF_CFLAGS $LIBBPF_LDLIBS >/dev/null 2>&1
++    $CC -o $TMPDIR/libbpf_sec_test $TMPDIR/libbpf_sec_test.c $LIBBPF_CFLAGS $LIBBPF_LDLIBS $LDFLAGS >/dev/null 2>&1
+     local ret=$?
+ 
+     rm -f $TMPDIR/libbpf_sec_test.c $TMPDIR/libbpf_sec_test
diff --git a/package/network/utils/iproute2/patches/195-build_variant_ip_tc.patch b/package/network/utils/iproute2/patches/195-build_variant_ip_tc.patch
new file mode 100644
index 0000000..6ecf556
--- /dev/null
+++ b/package/network/utils/iproute2/patches/195-build_variant_ip_tc.patch
@@ -0,0 +1,22 @@
+--- a/ip/Makefile
++++ b/ip/Makefile
+@@ -28,7 +28,7 @@ STATIC_SYM_SOURCES:=$(filter-out $(STATI
+ 
+ ALLOBJ=$(IPOBJ) $(RTMONOBJ)
+ SCRIPTS=routel
+-TARGETS=ip rtmon
++TARGETS=$(findstring ip,$(BUILD_VARIANT)) rtmon
+ 
+ all: $(TARGETS) $(SCRIPTS)
+ 
+--- a/tc/Makefile
++++ b/tc/Makefile
+@@ -120,7 +120,7 @@ MODDESTDIR := $(DESTDIR)$(LIBDIR)/tc
+ 	$(QUIET_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -shared -fpic $< -o $@
+ 
+ 
+-all: tc $(TCSO)
++all: $(findstring tc,$(BUILD_VARIANT)) $(TCSO)
+ 
+ tc: $(TCOBJ) $(LIBNETLINK) libtc.a
+ 	$(QUIET_LINK)$(CC) $^ $(LDFLAGS) $(LDLIBS) -o $@
diff --git a/package/network/utils/iproute2/patches/200-drop_libbsd_dependency.patch b/package/network/utils/iproute2/patches/200-drop_libbsd_dependency.patch
new file mode 100644
index 0000000..38193be
--- /dev/null
+++ b/package/network/utils/iproute2/patches/200-drop_libbsd_dependency.patch
@@ -0,0 +1,19 @@
+--- a/configure
++++ b/configure
+@@ -413,14 +413,8 @@ EOF
+     if $CC -I$INCLUDE -o $TMPDIR/strtest $TMPDIR/strtest.c >/dev/null 2>&1; then
+ 	echo "no"
+     else
+-	if ${PKG_CONFIG} libbsd --exists; then
+-		echo 'CFLAGS += -DHAVE_LIBBSD' "$(${PKG_CONFIG} libbsd --cflags)" >>$CONFIG
+-		echo 'LDLIBS +=' "$(${PKG_CONFIG} libbsd --libs)" >> $CONFIG
+-		echo "no"
+-	else
+-		echo 'CFLAGS += -DNEED_STRLCPY' >>$CONFIG
+-		echo "yes"
+-	fi
++	echo 'CFLAGS += -DNEED_STRLCPY' >>$CONFIG
++	echo "yes"
+     fi
+     rm -f $TMPDIR/strtest.c $TMPDIR/strtest
+ }
diff --git a/package/network/utils/iproute2/patches/300-selinux-configurable.patch b/package/network/utils/iproute2/patches/300-selinux-configurable.patch
new file mode 100644
index 0000000..9f07d31
--- /dev/null
+++ b/package/network/utils/iproute2/patches/300-selinux-configurable.patch
@@ -0,0 +1,11 @@
+--- a/configure
++++ b/configure
+@@ -342,7 +342,7 @@ check_libbpf()
+ check_selinux()
+ # SELinux is a compile time option in the ss utility
+ {
+-	if ${PKG_CONFIG} libselinux --exists; then
++	if [ "${HAVE_SELINUX}" = "y" ] && ${PKG_CONFIG} libselinux --exists; then
+ 		echo "HAVE_SELINUX:=y" >>$CONFIG
+ 		echo "yes"
+ 
diff --git a/package/network/utils/iproute2/patches/400-rdma-include-libgen.h-for-basename.patch b/package/network/utils/iproute2/patches/400-rdma-include-libgen.h-for-basename.patch
new file mode 100644
index 0000000..530d2bc
--- /dev/null
+++ b/package/network/utils/iproute2/patches/400-rdma-include-libgen.h-for-basename.patch
@@ -0,0 +1,10 @@
+--- a/rdma/rdma.h
++++ b/rdma/rdma.h
+@@ -16,6 +16,7 @@
+ #include <rdma/rdma_user_cm.h>
+ #include <time.h>
+ #include <net/if_arp.h>
++#include <libgen.h>
+ 
+ #include "list.h"
+ #include "utils.h"
diff --git a/package/network/utils/ipset/Makefile b/package/network/utils/ipset/Makefile
new file mode 100644
index 0000000..c62bbd8
--- /dev/null
+++ b/package/network/utils/ipset/Makefile
@@ -0,0 +1,75 @@
+
+# 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:=7.21
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://ipset.netfilter.org
+PKG_HASH:=e2c6ce4fcf3acb3893ca5d35c86935f80ad76fc5ccae601185842df760e0bc69
+
+PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
+PKG_LICENSE:=GPL-2.0
+PKG_CPE_ID:=cpe:/a:netfilter:ipset
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ipset/Default
+  SECTION:=net
+  CATEGORY:=Network
+  DEPENDS+= +kmod-ipt-ipset +libmnl
+  TITLE:=IPset administration utility
+  URL:=http://ipset.netfilter.org/
+endef
+
+define Package/ipset
+$(call Package/ipset/Default)
+  DEPENDS+= +libipset
+endef
+
+define Package/libipset
+$(call Package/ipset/Default)
+  ABI_VERSION:=13
+endef
+
+CONFIGURE_ARGS += \
+	--disable-static \
+	--with-kbuild="$(LINUX_DIR)"
+
+TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed
+
+MAKE_FLAGS += \
+	ARCH="$(LINUX_KARCH)" \
+	SHELL="$(BASH)"
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(1)/usr/include $(1)/usr/lib $(1)/usr/lib/pkgconfig
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/libipset $(1)/usr/include/
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libipset.so* $(1)/usr/lib/
+	$(CP) $(PKG_BUILD_DIR)/lib/libipset.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/ipset/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(CP) $(PKG_INSTALL_DIR)/usr/sbin/ipset $(1)/usr/sbin/
+	$(CP) $(PKG_INSTALL_DIR)/usr/sbin/ipset-translate $(1)/usr/sbin/
+endef
+
+define Package/libipset/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libipset*.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,libipset))
+$(eval $(call BuildPackage,ipset))
diff --git a/package/network/utils/ipset/patches/0001-include-libgen.h-for-basename.patch b/package/network/utils/ipset/patches/0001-include-libgen.h-for-basename.patch
new file mode 100644
index 0000000..fb86bba
--- /dev/null
+++ b/package/network/utils/ipset/patches/0001-include-libgen.h-for-basename.patch
@@ -0,0 +1,12 @@
+--- a/src/ipset.c
++++ b/src/ipset.c
+@@ -6,8 +6,8 @@
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  */
+-#define _GNU_SOURCE
+ #include <assert.h>			/* assert */
++#include <libgen.h>			/* basename */
+ #include <stdio.h>			/* fprintf */
+ #include <stdlib.h>			/* exit */
+ #include <string.h>			/* strcmp */
diff --git a/package/network/utils/ipt_trigger/inc/ipt_trigger.h b/package/network/utils/ipt_trigger/inc/ipt_trigger.h
new file mode 100644
index 0000000..886e201
--- /dev/null
+++ b/package/network/utils/ipt_trigger/inc/ipt_trigger.h
@@ -0,0 +1,24 @@
+#ifndef _IPT_TRIGGER_H_target
+#define _IPT_TRIGGER_H_target
+
+#define TRIGGER_TIMEOUT 600	/* 600 secs */
+
+enum ipt_trigger_type
+{
+	IPT_TRIGGER_DNAT = 1,
+	IPT_TRIGGER_IN = 2,
+	IPT_TRIGGER_OUT = 3
+};
+
+struct ipt_trigger_ports {
+	u_int16_t mport[2];	/* Related destination port range */
+	u_int16_t rport[2];	/* Port range to map related destination port range to */
+};
+
+struct ipt_trigger_info {
+	enum ipt_trigger_type type;
+	u_int16_t proto;	/* Related protocol */
+	struct ipt_trigger_ports ports;
+};
+
+#endif /*_IPT_TRIGGER_H_target*/
diff --git a/package/network/utils/ipt_trigger/ipt_trigger_ko/Makefile b/package/network/utils/ipt_trigger/ipt_trigger_ko/Makefile
new file mode 100644
index 0000000..2443d84
--- /dev/null
+++ b/package/network/utils/ipt_trigger/ipt_trigger_ko/Makefile
@@ -0,0 +1,58 @@
+#
+# Copyright (C) 2008 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
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/netfilter.mk
+
+PKG_NAME:=ipt_trigger
+PKG_RELEASE:=1
+PKG_PATH=$(TOPDIR)/package/network/utils/ipt_trigger
+
+define KernelPackage/ipt_trigger
+  SUBMENU:=Netfilter Extensions
+  TITLE:=kernel module for port trigger
+  DEPENDS:=+kmod-ipt-core +kmod-ipt-conntrack +kmod-ipt-nat +kmod-x_tables
+  FILES:=$(PKG_BUILD_DIR)/ipt_trigger.ko
+  KCONFIG:=CONFIG_TRIGGER=y \
+	CONFIG_TRIGGER_MASTER=y
+  AUTOLOAD:=$(call AutoLoad,50,ipt_trigger)
+  DEFAULT:=N
+endef
+
+define KernelPackage/ipt_trigger/description
+  Kernel module for port trigger
+endef
+
+EXTRA_KCONFIG:= \
+	CONFIG_IPT_TRIGGER=m
+
+EXTRA_CFLAGS:= \
+	$(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
+	$(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \
+
+MAKE_OPTS:= \
+	ARCH="$(LINUX_KARCH)" \
+	CROSS_COMPILE="$(TARGET_CROSS)" \
+	M="$(PKG_BUILD_DIR)" \
+	EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
+	$(EXTRA_KCONFIG)
+
+define Build/Prepare
+	mkdir -p $(PKG_BUILD_DIR)
+	$(CP) $(PKG_PATH)/ipt_trigger_ko/src/* $(PKG_BUILD_DIR)/
+	$(CP) $(PKG_PATH)/inc/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+	$(MAKE) -C "$(LINUX_DIR)" \
+		$(MAKE_OPTS) \
+		modules
+endef
+
+$(eval $(call KernelPackage,ipt_trigger))
diff --git a/package/network/utils/ipt_trigger/ipt_trigger_ko/src/Kconfig b/package/network/utils/ipt_trigger/ipt_trigger_ko/src/Kconfig
new file mode 100644
index 0000000..019411f
--- /dev/null
+++ b/package/network/utils/ipt_trigger/ipt_trigger_ko/src/Kconfig
@@ -0,0 +1,6 @@
+config ipt_trigger
+	tristate "ipt trigger port"
+	default y
+	help
+		haha
+
diff --git a/package/network/utils/ipt_trigger/ipt_trigger_ko/src/Makefile b/package/network/utils/ipt_trigger/ipt_trigger_ko/src/Makefile
new file mode 100644
index 0000000..82bc220
--- /dev/null
+++ b/package/network/utils/ipt_trigger/ipt_trigger_ko/src/Makefile
@@ -0,0 +1 @@
+obj-m += ipt_trigger.o  
diff --git a/package/network/utils/ipt_trigger/ipt_trigger_ko/src/ipt_trigger.c b/package/network/utils/ipt_trigger/ipt_trigger_ko/src/ipt_trigger.c
new file mode 100644
index 0000000..cb1441a
--- /dev/null
+++ b/package/network/utils/ipt_trigger/ipt_trigger_ko/src/ipt_trigger.c
@@ -0,0 +1,380 @@
+/* Kernel module to match the port-ranges, trigger related port-ranges,
+ * and alters the destination to a local IP address.
+ *
+ * Description:
+ *   This is kernel module for port-triggering.
+ *
+ *   The module follows the Netfilter framework, called extended packet 
+ *   matching modules. 
+ */
+
+#include <linux/types.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/timer.h>
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/netdevice.h>
+#include <linux/if.h>
+#include <linux/inetdevice.h>
+#include <net/protocol.h>
+#include <net/checksum.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/types.h>
+
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/nf_nat.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_tuple.h>
+#include <net/netfilter/nf_nat.h>
+#include "ipt_trigger.h"
+
+MODULE_LICENSE("GPL");
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+struct ipt_trigger {
+	struct list_head list;		/* Trigger list */
+	struct timer_list timeout;	/* Timer for list destroying */
+	u_int32_t srcip;		/* Outgoing source address */
+	u_int32_t dstip;		/* Outgoing destination address */
+	u_int16_t mproto;		/* Trigger protocol */
+	u_int16_t rproto;		/* Related protocol */
+	struct ipt_trigger_ports ports;	/* Trigger and related ports */
+	u_int8_t reply;			/* Confirm a reply connection */
+};
+
+
+LIST_HEAD(trigger_list);
+DEFINE_SPINLOCK(ip_trigger_lock);
+
+static void trigger_refresh(struct ipt_trigger *trig, unsigned long extra_jiffies)
+{
+    DEBUGP("%s: \n", __FUNCTION__);
+    NF_CT_ASSERT(trig);
+    spin_lock_bh(&ip_trigger_lock);
+
+    /* Need del_timer for race avoidance (may already be dying). */
+    if (del_timer(&trig->timeout)) {
+	trig->timeout.expires = jiffies + extra_jiffies;
+	add_timer(&trig->timeout);
+    }
+
+    spin_unlock_bh(&ip_trigger_lock);
+}
+
+static void __del_trigger(struct ipt_trigger *trig)
+{
+    DEBUGP("%s: \n", __FUNCTION__);
+    NF_CT_ASSERT(trig);
+
+     /* delete from 'trigger_list' */
+    list_del(&trig->list);
+    kfree(trig);
+}
+
+static void trigger_timeout(struct timer_list *t)
+{
+    struct ipt_trigger *trig = container_of(t, struct ipt_trigger, timeout);
+
+    DEBUGP("trigger list %p timed out\n", trig);
+    spin_lock_bh(&ip_trigger_lock);
+    __del_trigger(trig);
+    spin_unlock_bh(&ip_trigger_lock);
+}
+
+static unsigned int
+add_new_trigger(struct ipt_trigger *trig)
+{
+    struct ipt_trigger *trigger_new;
+
+    DEBUGP("!!!!!!!!!!!! %s !!!!!!!!!!!\n", __FUNCTION__);
+    spin_lock_bh(&ip_trigger_lock);
+    trigger_new = (struct ipt_trigger *)
+	kzalloc(sizeof(struct ipt_trigger), GFP_ATOMIC);
+
+    if (!trigger_new) {
+	spin_unlock_bh(&ip_trigger_lock);
+	DEBUGP("%s: OOM allocating trigger list\n", __FUNCTION__);
+	return -ENOMEM;
+    }
+
+    memcpy(trigger_new, trig, sizeof(*trig));
+    INIT_LIST_HEAD(&trigger_new->list);
+
+    /* add to global table of trigger */
+    list_add(&trigger_new->list, &trigger_list);
+    /* add and start timer if required */
+#if 0
+    init_timer(&trigger_new->timeout);
+    trigger_new->timeout.data = (unsigned long)trigger_new;
+    trigger_new->timeout.function = trigger_timeout;
+    trigger_new->timeout.expires = jiffies + (TRIGGER_TIMEOUT * HZ);
+    add_timer(&trigger_new->timeout);
+#else
+    timer_setup(&trigger_new->timeout, trigger_timeout, 0);
+#endif
+
+    spin_unlock_bh(&ip_trigger_lock);
+
+    return 0;
+}
+
+static inline int trigger_out_matched(const struct ipt_trigger *i,
+	const u_int16_t proto, const u_int16_t dport)
+{
+    /* DEBUGP("%s: i=%p, proto= %d, dport=%d.\n", __FUNCTION__, i, proto, dport);
+    DEBUGP("%s: Got one, mproto= %d, mport[0..1]=%d, %d.\n", __FUNCTION__, 
+	    i->mproto, i->ports.mport[0], i->ports.mport[1]); */
+
+    return ((i->mproto == proto) && (i->ports.mport[0] <= dport) 
+	    && (i->ports.mport[1] >= dport));
+}
+static inline int trigger_in_matched(const struct ipt_trigger *i,
+	const u_int16_t proto, const u_int16_t dport)
+{
+    /* DEBUGP("%s: i=%p, proto= %d, dport=%d.\n", __FUNCTION__, i, proto, dport);
+    DEBUGP("%s: Got one, rproto= %d, rport[0..1]=%d, %d.\n", __FUNCTION__, 
+	    i->rproto, i->ports.rport[0], i->ports.rport[1]); */
+    u_int16_t rproto = i->rproto;
+
+    if (!rproto)
+	rproto = proto;
+
+    return ((rproto == proto) && (i->ports.rport[0] <= dport) 
+	    && (i->ports.rport[1] >= dport));
+}
+/*in -- 0; out -- 1*/
+enum
+{
+	TRIGGER_IN_MATCH,
+	TRIGGER_OUT_MATCH,
+};
+struct ipt_trigger * trigger_find_match(struct list_head *list_head,	const u_int16_t proto, const u_int16_t dport	, int type)
+{
+	const struct list_head *_i, *_j = NULL;	
+
+	list_for_each(_i, list_head)
+	{
+		if(type == TRIGGER_IN_MATCH)
+		{
+			if (trigger_in_matched((const struct ipt_trigger*)_i , proto,	dport)) 
+				{	
+					_j = _i;			
+					break;				
+				}
+		}
+		else if(type == TRIGGER_OUT_MATCH)
+		{
+				if (trigger_out_matched((const struct ipt_trigger*)_i , proto,	dport)) 
+					{	
+						_j = _i;			
+						break;				
+					}
+			}
+			
+		}
+			
+		
+		if(_j)
+		{
+			return (struct ipt_trigger *)_j;	
+		}
+		else
+		{
+			return NULL;
+		}
+}
+
+static unsigned int
+trigger_out(struct sk_buff *skb,
+		unsigned int hooknum,
+		const struct net_device *in,
+		const struct net_device *out,
+		const void *targinfo)
+{
+    const struct ipt_trigger_info *info = targinfo;
+    struct ipt_trigger trig, *found;
+    const struct iphdr *iph = ip_hdr(skb);
+    struct tcphdr *tcph = (void *)iph + iph->ihl*4;	/* Might be TCP, UDP */
+
+    DEBUGP("############# %s ############\n", __FUNCTION__);
+	
+    /* Check if the trigger range has already existed in 'trigger_list'. */
+    found = trigger_find_match(&trigger_list, iph->protocol, ntohs(tcph->dest),	TRIGGER_OUT_MATCH);
+
+    if (found) {
+	/* Yeah, it exists. We need to update(delay) the destroying timer. */
+	trigger_refresh(found, TRIGGER_TIMEOUT * HZ);
+	/* In order to allow multiple hosts use the same port range, we update
+	   the 'saddr' after previous trigger has a reply connection. */
+	if (found->reply)
+	    found->srcip = iph->saddr;
+    }
+    else {
+	/* Create new trigger */
+	memset(&trig, 0, sizeof(trig));
+	trig.srcip = iph->saddr;
+	trig.mproto = iph->protocol;
+	trig.rproto = info->proto;
+	memcpy(&trig.ports, &info->ports, sizeof(struct ipt_trigger_ports));
+	add_new_trigger(&trig);	/* Add the new 'trig' to list 'trigger_list'. */
+    }
+
+    return XT_CONTINUE;	/* We don't block any packet. */
+}
+
+
+static unsigned int
+trigger_in(struct sk_buff *skb,
+		unsigned int hooknum,
+		const struct net_device *in,
+		const struct net_device *out,
+		const void *targinfo)
+{
+    struct ipt_trigger *found;
+    const struct iphdr *iph = ip_hdr(skb);
+    struct tcphdr *tcph = (void *)iph + iph->ihl*4;	/* Might be TCP, UDP */
+    /* Check if the trigger-ed range has already existed in 'trigger_list'. */
+    found = trigger_find_match(&trigger_list,  iph->protocol, ntohs(tcph->dest),	TRIGGER_IN_MATCH);
+    if (found) {
+	DEBUGP("############# %s ############\n", __FUNCTION__);
+	/* Yeah, it exists. We need to update(delay) the destroying timer. */
+	trigger_refresh(found, TRIGGER_TIMEOUT * HZ);
+	return NF_ACCEPT;	/* Accept it, or the imcoming packet could be 
+				   dropped in the FORWARD chain */
+    }
+ 
+    return XT_CONTINUE;	/* Our job is the interception. */
+}
+
+static unsigned int
+trigger_dnat(struct sk_buff *skb,
+		unsigned int hooknum,
+		const struct net_device *in,
+		const struct net_device *out,
+		const void *targinfo)
+{
+    struct ipt_trigger *found;
+    const struct iphdr *iph = ip_hdr(skb);
+    struct tcphdr *tcph = (void *)iph + iph->ihl*4;	/* Might be TCP, UDP */
+    struct nf_conn *ct;
+    enum ip_conntrack_info ctinfo;
+    struct nf_nat_range2 newrange = { 0 };
+
+    NF_CT_ASSERT(hooknum == NF_INET_PRE_ROUTING);
+    /* Check if the trigger-ed range has already existed in 'trigger_list'. */
+    found = trigger_find_match(&trigger_list,  iph->protocol, ntohs(tcph->dest),	TRIGGER_IN_MATCH);
+
+    if (!found || !found->srcip)
+	return XT_CONTINUE;	/* We don't block any packet. */
+
+    DEBUGP("############# %s ############\n", __FUNCTION__);
+    found->reply = 1;	/* Confirm there has been a reply connection. */
+    ct = nf_ct_get(skb, &ctinfo);
+    NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW));
+
+    DEBUGP("%s: got ", __FUNCTION__);
+    nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+
+    /* Alter the destination of imcoming packet. */
+    newrange.flags = NF_NAT_RANGE_MAP_IPS;
+    newrange.min_addr = newrange.max_addr = (union nf_inet_addr)found->srcip;
+    newrange.min_proto.all = newrange.max_proto.all = 0;
+
+    /* Hand modified range to generic setup. */
+    return nf_nat_setup_info(ct, &newrange, hooknum);
+}
+static unsigned int
+trigger_target (struct sk_buff *skb,
+			   const struct xt_action_param *par)
+{
+    const struct ipt_trigger_info *info = par->targinfo;
+    const struct iphdr *iph = ip_hdr(skb);
+
+    /* DEBUGP("%s: type = %s\n", __FUNCTION__, 
+	    (info->type == IPT_TRIGGER_DNAT) ? "dnat" :
+	    (info->type == IPT_TRIGGER_IN) ? "in" : "out"); */
+
+    /* The Port-trigger only supports TCP and UDP. */
+    if ((iph->protocol != IPPROTO_TCP) && (iph->protocol != IPPROTO_UDP))
+	return XT_CONTINUE;
+
+    if (info->type == IPT_TRIGGER_OUT)
+	return trigger_out(skb, par->state->hook, par->state->in, par->state->out, par->targinfo);
+    else if (info->type == IPT_TRIGGER_IN)
+	return trigger_in(skb, par->state->hook, par->state->in, par->state->out, par->targinfo);
+    else if (info->type == IPT_TRIGGER_DNAT)
+        return trigger_dnat(skb, par->state->hook, par->state->in, par->state->out, par->targinfo);
+
+    return XT_CONTINUE;
+}
+
+static int
+trigger_check(const struct xt_tgchk_param *par)
+{
+	const struct ipt_trigger_info *info = par->targinfo;
+	struct list_head *cur_item, *tmp_item;
+
+	if ((strcmp(par->table, "mangle") == 0)) {
+		DEBUGP("trigger_check: bad table `%s'.\n", par->table);
+		return -EINVAL;
+	}
+	if (par->hook_mask & ~((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_FORWARD))) {
+		DEBUGP("trigger_check: bad hooks %x.\n", par->hook_mask);
+		return -EINVAL;
+	}
+	if (info->proto) {
+	    if (info->proto != IPPROTO_TCP && info->proto != IPPROTO_UDP) {
+		DEBUGP("trigger_check: bad proto %d.\n", info->proto);
+		return -EINVAL;
+	    }
+	}
+	if (info->type == IPT_TRIGGER_OUT) {
+	    if (!info->ports.mport[0] || !info->ports.rport[0]) {
+		DEBUGP("trigger_check: Try 'iptbles -j TRIGGER -h' for help.\n");
+		return -EINVAL;
+	    }
+	}
+
+	/* Empty the 'trigger_list' */
+	list_for_each_safe(cur_item, tmp_item, &trigger_list) {
+	    struct ipt_trigger *trig = (void *)cur_item;
+
+	    DEBUGP("%s: list_for_each_safe(): %p.\n", __FUNCTION__, trig);
+	    del_timer(&trig->timeout);
+	    __del_trigger(trig);
+	}
+
+	return 0;
+}
+
+static struct xt_target redirect_reg = { 
+	.name 		= "TRIGGER",
+	.family		= AF_INET,
+	.target 	= trigger_target, 
+	.targetsize	= sizeof(struct ipt_trigger_info),
+	.checkentry 	= trigger_check,
+	.me 		= THIS_MODULE,
+};
+
+static int __init init(void)
+{
+	return xt_register_target(&redirect_reg);
+}
+
+static void __exit fini(void)
+{
+	xt_unregister_target(&redirect_reg);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/package/network/utils/ipt_trigger/libipt_trigger/Makefile b/package/network/utils/ipt_trigger/libipt_trigger/Makefile
new file mode 100644
index 0000000..7e9d0d2
--- /dev/null
+++ b/package/network/utils/ipt_trigger/libipt_trigger/Makefile
@@ -0,0 +1,67 @@
+#
+# Copyright (C) 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
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/netfilter.mk
+
+PKG_NAME:=libipt_trigger
+PKG_VERSION:=2014
+PKG_RELEASE:=1
+
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+PKG_PATH:=$(TOPDIR)/package/network/utils/ipt_trigger
+SVC_SOURCE_DIR:=$(PKG_PATH)/libipt_trigger/src
+PKG_BUILD_PARALLEL:=0
+
+define Package/libipt_trigger
+  SECTION:=libipt_trigger
+  CATEGORY:=Network
+  TITLE:=ASR iptable addon to support port trigger
+  DEPENDS:=+iptables +kmod-ipt_trigger
+  DEFAULT:=N
+endef
+
+define Package/libipt_trigger/description
+   iptable addon to support port trigger
+endef
+
+TARGET_CFLAGS += -ffunction-sections -fdata-sections
+TARGET_LDFLAGS += -Wl,--gc-sections
+
+define Build/Compile
+	$(MAKE) $(PKG_JOBS) -C $(SVC_SOURCE_DIR) \
+		SUBTARGET="$(SUBTARGET)" \
+		CROSS_COMPILE="$(TARGET_CROSS)" \
+		EXTRA_CFLAGS="$(TARGET_CFLAGS) -I$(PKG_PATH)/inc -I$(STAGING_DIR)/usr/include -I$(TOOLCHAIN_DIR)/include" \
+		LD_FLAGS="$(TARGET_LDFLAGS) -L$(TOOLCHAIN_DIR)/lib/"\
+		INSTALL_DIR="$(PKG_INSTALL_DIR)" \
+		OBJ_DIR="$(PKG_BUILD_DIR)/obj" \
+		compile
+endef
+
+define Build/Clean
+@if [ -d $(PKG_BUILD_DIR) ]; then \
+	$(MAKE) $(PKG_JOBS) -C $(SVC_SOURCE_DIR) \
+		CROSS_COMPILE="$(TARGET_CROSS)" \
+		EXTRA_CFLAGS="$(TARGET_CFLAGS)" \
+		LD_FLAGS="$(TARGET_LDFLAGS)" \
+		INSTALL_DIR="$(PKG_INSTALL_DIR)" \
+		OBJ_DIR="$(PKG_BUILD_DIR)/obj" \
+		clean; \
+fi
+endef
+
+define Package/libipt_trigger/install
+	$(INSTALL_DIR) $(1)/usr/lib/iptables
+	$(CP) $(PKG_INSTALL_DIR)/lib/libipt_TRIGGER.so $(1)/usr/lib/iptables/
+endef
+$(eval $(call BuildPackage,libipt_trigger))
+
+
diff --git a/package/network/utils/ipt_trigger/libipt_trigger/src/Makefile b/package/network/utils/ipt_trigger/libipt_trigger/src/Makefile
new file mode 100644
index 0000000..878e7fa
--- /dev/null
+++ b/package/network/utils/ipt_trigger/libipt_trigger/src/Makefile
@@ -0,0 +1,76 @@
+#/******************************************************************************
+#*(C) Copyright 2008 Marvell International Ltd.
+#* All Rights Reserved
+#******************************************************************************/
+BUILDROOT := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
+
+#include $(TOPDIR)/rules.mk
+#include rules.make
+include $(BUILDROOT)/rules.make
+
+$(eval $(call define-local-build-dir, objs_libipt_TRIGGER))
+
+
+dtarget := $(LOCAL_BUILD_DIR)/libipt_TRIGGER.so 
+
+compile: $(dtarget)
+
+LOCAL_SRC_FILES := \
+	libipt_TRIGGER.c \
+
+LINUX_KERNEL_INC := $(TOPDIR)/marvell/linux/include
+USER_LINUX_INC  := $(TOPDIR)/marvell/linux/user_headers/include
+IPTABLES_INCLUDE = $(KERNEL_BUILD_DIR)/iptables.1.4.21/include
+
+LOCAL_CFLAGS += -DMARVELL_EXTENDED
+CFLAGS += $(LOCAL_C_INCLUDES)
+CFLAGS += $(LOCAL_CFLAGS)
+CFLAGS += $(LOCAL_CPPFLAGS)
+	
+
+$(eval $(call add-many-objects-rule, ipt_trigger_src, $(LOCAL_SRC_FILES),,))
+
+#prepare:
+#	@echo "begin make dir"
+#	$(MRVL_HIDE)mkdir -p $(PXA_TARGET_OLIB)
+#	$(MRVL_HIDE)mkdir -p $(LOCAL_BUILD_DIR)
+
+all: modules libipt_TRIGGER.so
+
+modules: $(dtarget)
+
+	@echo "KERNEL_SRC $(KERNEL_SRC)" 
+
+#$(dtarget): libipt_TRIGGER.c
+	#$(MRVL_HIDE)$(CC) -DIPTABLES_VERSION=\"1.4.21\" -I$(IPTABLES_INCLUDE) -I$(USER_LINUX_INC) -I$(TOPDIR)/package/network/utils/ipt_trigger/inc -fPIC -c libipt_TRIGGER.c \
+	#		-o $(LOCAL_BUILD_DIR)/libipt_TRIGGER.o
+	#$(MRVL_HIDE)$(CC) -shared -o $(dtarget) $(LOCAL_BUILD_DIR)/libipt_TRIGGER.o
+
+$(dtarget): 
+	@echo "begin make dir"
+	$(MRVL_HIDE)mkdir -p $(PXA_TARGET_OLIB)
+	$(MRVL_HIDE)mkdir -p $(LOCAL_BUILD_DIR)
+	@echo "LOCAL_BUILD_DIR $(LOCAL_BUILD_DIR)"
+	@echo "  LD     $@"
+	$(MRVL_HIDE)$(CC) -DIPTABLES_VERSION=\"1.4.21\" -I$(IPTABLES_INCLUDE) -I$(USER_LINUX_INC) -I$(TOPDIR)/package/network/utils/ipt_trigger/inc -fPIC -c libipt_TRIGGER.c \
+			-o $(LOCAL_BUILD_DIR)/libipt_TRIGGER.o
+	$(MRVL_HIDE)$(CC) -shared -o $(dtarget) $(LOCAL_BUILD_DIR)/libipt_TRIGGER.o
+	$(call copy_elf,$(dtarget),lib)
+
+#$(dtarget): prepare $(libipt_TRIGGER_src_oo) alwayslink
+#	@echo "LOCAL_BUILD_DIR $(LOCAL_BUILD_DIR)"
+#	@echo "  LD     $@"
+#	$(MRVL_HIDE)$(CC) $(CFLAGS) -DIPTABLES_VERSION=\"1.4.21\" -I$(IPTABLES_INCLUDE) -I$(USER_LINUX_INC) -I$(TOPDIR)/package/network/utils/ipt_trigger/inc -fPIC -c $(LOCAL_SRC_FILES) \
+#	  -o $@ $(libipt_TRIGGER_src_oo) $(LIBS) 
+#	$(call copy_elf,$(dtarget),lib)
+
+install:
+	@echo "install done"
+clean:
+	$(call clean_target, $(dtarget), bin)
+	$(MRVL_HIDE)rm -rf $(LOCAL_BUILD_DIR)
+
+ifeq "$(filter clean ,$(MAKECMDGOALS))" ""
+-include $(ipt_TRIGGER_src_dd)
+endif
+
diff --git a/package/network/utils/ipt_trigger/libipt_trigger/src/libipt_TRIGGER.c b/package/network/utils/ipt_trigger/libipt_trigger/src/libipt_TRIGGER.c
new file mode 100644
index 0000000..fdef8f1
--- /dev/null
+++ b/package/network/utils/ipt_trigger/libipt_trigger/src/libipt_TRIGGER.c
@@ -0,0 +1,206 @@
+/* Port-triggering target. 
+ *
+ */
+
+/* Shared library add-on to iptables to add port-trigger support. */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <linux/netfilter/nf_nat.h>
+#include <ipt_trigger.h>
+
+/* Function which prints out usage message. */
+static void
+TRIGGER_help(void)
+{
+	printf(
+"TRIGGER v%s options:\n"
+" --trigger-type (dnat|in|out)\n"
+"				Trigger type\n"
+" --trigger-proto proto\n"
+"				Trigger protocol\n"
+" --trigger-match port[-port]\n"
+"				Trigger destination port range\n"
+" --trigger-relate port[-port]\n"
+"				Port range to map related destination port range to.\n\n",
+IPTABLES_VERSION);
+}
+
+enum{
+		TRIGGER_TYPE = 0,
+		TRIGGER_PROTO,
+		TRIGGER_MATCH,
+		TRIGGER_RELATE,
+	};
+static const struct xt_option_entry TRIGGER_opts[] = {
+	{.name = "trigger-type", .id = TRIGGER_TYPE, .type = XTTYPE_STRING},
+	{.name = "trigger-proto", .id = TRIGGER_PROTO, .type = XTTYPE_STRING},
+	{.name = "trigger-match", .id = TRIGGER_MATCH, .type = XTTYPE_STRING},
+	{.name = "trigger-relate", .id = TRIGGER_RELATE, .type = XTTYPE_STRING},
+	XTOPT_TABLEEND,
+};
+static void TRIGGER_init(struct xt_entry_target *t)
+{
+
+}
+
+/* Parses ports */
+static void
+TRIGGER_parse_ports(const char *arg, u_int16_t *ports)
+{
+	const char *dash;
+	int port;
+
+	port = atoi(arg);
+	if (port == 0 || port > 65535)
+		xtables_error(PARAMETER_PROBLEM, "Port range `%s' invalid\n", arg);
+
+	dash = strchr(arg, ':');
+	if (!dash)
+		ports[0] = ports[1] = port;
+	else {
+		int maxport;
+
+		maxport = atoi(dash + 1);
+		if (maxport == 0 || maxport > 65535)
+			xtables_error(PARAMETER_PROBLEM,
+				   "Port range `%s' invalid\n", dash+1);
+		if (maxport < port)
+			xtables_error(PARAMETER_PROBLEM,
+				   "Port range `%s' invalid\n", arg);
+		ports[0] = port;
+		ports[1] = maxport;
+	}
+}
+
+/* Function which parses command options; returns true if it
+   ate an option */
+static int
+TRIGGER_parse(struct xt_option_call *cb)
+{
+	struct ipt_trigger_info *info = (struct ipt_trigger_info *)(*cb->target)->data;
+
+	switch (cb->entry->id) {
+	case TRIGGER_TYPE:
+		if (!strcasecmp(cb->arg, "dnat"))
+			info->type = IPT_TRIGGER_DNAT;
+		else if (!strcasecmp(cb->arg, "in"))
+			info->type = IPT_TRIGGER_IN;
+		else if (!strcasecmp(cb->arg, "out"))
+			info->type = IPT_TRIGGER_OUT;
+		else
+			xtables_error(PARAMETER_PROBLEM,
+				   "unknown type `%s' specified", cb->arg);
+		return 1;
+
+	case TRIGGER_PROTO:
+		if (!strcasecmp(cb->arg, "tcp"))
+			info->proto = IPPROTO_TCP;
+		else if (!strcasecmp(cb->arg, "udp"))
+			info->proto = IPPROTO_UDP;
+		else if (!strcasecmp(cb->arg, "all"))
+			info->proto = 0;
+		else
+			xtables_error(PARAMETER_PROBLEM,
+				   "unknown protocol `%s' specified", cb->arg);
+		return 1;
+
+	case TRIGGER_MATCH:
+		if (cb->arg && (strcmp(cb->arg, "!") == 0))
+		{
+			cb->invert = 1;
+			xtables_error(PARAMETER_PROBLEM,
+				   "Unexpected `!' after --trigger-match");
+		}
+		TRIGGER_parse_ports(cb->arg, info->ports.mport);
+		return 1;
+
+	case TRIGGER_RELATE:
+		if (cb->arg && (strcmp(cb->arg, "!") == 0))
+		{
+			cb->invert = 1;
+			xtables_error(PARAMETER_PROBLEM,
+				   "Unexpected `!' after --trigger-match");
+		}
+		TRIGGER_parse_ports(cb->arg, info->ports.rport);
+		cb->xflags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+		return 1;
+
+	default:
+		return 0;
+	}
+}
+
+/* Final check; don't care. */
+static void TRIGGER_final_check(unsigned int flags)
+{
+}
+
+/* Prints out the targinfo. */
+static void
+TRIGGER_print(const struct ipt_ip *ip,
+      const struct xt_entry_target *target,
+      int numeric)
+{
+	struct ipt_trigger_info *info = (const void *)target->data;
+
+	printf("TRIGGER ");
+	if (info->type == IPT_TRIGGER_DNAT)
+		printf("type:dnat ");
+	else if (info->type == IPT_TRIGGER_IN)
+		printf("type:in ");
+	else if (info->type == IPT_TRIGGER_OUT)
+		printf("type:out ");
+
+	if (info->proto == IPPROTO_TCP)
+		printf("tcp ");
+	else if (info->proto == IPPROTO_UDP)
+		printf("udp ");
+
+	printf("match:%hu", info->ports.mport[0]);
+	if (info->ports.mport[1] > info->ports.mport[0])
+		printf(":%hu", info->ports.mport[1]);
+	printf(" ");
+
+	printf("relate:%hu", info->ports.rport[0]);
+	if (info->ports.rport[1] > info->ports.rport[0])
+		printf(":%hu", info->ports.rport[1]);
+	printf(" ");
+}
+
+/* Saves the union ipt_targinfo in parsable form to stdout. */
+static void
+TRIGGER_save(const struct ipt_ip *ip, const struct xt_entry_target *target)
+{
+	struct ipt_trigger_info *info = (const void *)target->data;
+
+	printf("--trigger-proto ");
+	if (info->proto == IPPROTO_TCP)
+		printf("tcp ");
+	else if (info->proto == IPPROTO_UDP)
+		printf("udp ");
+	printf("--trigger-match %hu:%hu ", info->ports.mport[0], info->ports.mport[1]);
+	printf("--trigger-relate %hu:%hu ", info->ports.rport[0], info->ports.rport[1]);
+}
+
+static struct xtables_target trigger_tg_reg = {
+	.name		= "TRIGGER",
+	.version	= XTABLES_VERSION,
+	.family		= NFPROTO_IPV4,
+	.size		= XT_ALIGN(sizeof(struct ipt_trigger_info)),
+	.userspacesize	= XT_ALIGN(sizeof(struct ipt_trigger_info)),
+	.help		= TRIGGER_help,
+	.x6_parse	= TRIGGER_parse,
+	.print		= TRIGGER_print,
+	.save		= TRIGGER_save,
+	.x6_options	= TRIGGER_opts,
+};
+
+void _init(void)
+{
+	xtables_register_target(&trigger_tg_reg);
+}
diff --git a/package/network/utils/ipt_trigger/libipt_trigger/src/rules.make b/package/network/utils/ipt_trigger/libipt_trigger/src/rules.make
new file mode 100644
index 0000000..5ab965a
--- /dev/null
+++ b/package/network/utils/ipt_trigger/libipt_trigger/src/rules.make
@@ -0,0 +1,247 @@
+# main make rules for Marvell CM
+# this file is for generic linux. for Adnroid just see Android.mk makefiles
+
+#version -0.1
+#author - Chen Reichbach
+
+#for debug, remove this to see all compiler outputs.
+#MRVL_HIDE=@
+
+#general make rules
+#--------------------
+
+#compiler definisions
+ifneq "$(CROSS_COMPILE)" ""
+AS	:= $(CROSS_COMPILE)as
+CC	:= $(CROSS_COMPILE)gcc
+CPP	:= $(CROSS_COMPILE)c++
+AR	:= $(CROSS_COMPILE)ar rv
+LD	:= $(CROSS_COMPILE)ld
+STRIP	:= $(CROSS_COMPILE)strip
+RANLIB  := $(CROSS_COMPILE)ranlib
+else
+#we do not have $(CROSS_COMPILE), assume compilers were passed by caller.
+echo "WARNING: did not get CROSS_COMPILE"
+endif
+
+#define base path for build objects
+ifeq "$(OBJ_DIR)" ""
+OBJ_DIR := $(BUILDROOT)/obj
+endif
+SYMBOLS_DIR := $(OBJ_DIR)/symbol
+#define base path for build outputs
+ifeq "$(INSTALL_DIR)" ""
+INSTALL_DIR := $(BUILDROOT)/out
+endif
+#usefull paths:
+PXA_SRC_DIR := $(BUILDROOT)
+PXA_APPS_DIR := $(BUILDROOT)
+PXA_SCRIPTS_DIR	:= $(BUILDROOT)/scripts
+PXA_CONFIG_DIR := $(BUILDROOT)/configuration
+PXA_PREPASS_DIR := $(PXA_APPS_DIR)/prepass
+PXA_TARGET_OLIB := $(OBJ_DIR)/olibs
+PXA_GENERATED_FILES_DIR := $(OBJ_DIR)/gendir
+
+#start off with flags from user and then add spesific flags
+COMMONCFLAGS := $(EXTRA_CFLAGS)
+
+#warnings flags
+WARNINGFLAG	+= -Waggregate-return -Wmissing-noreturn -W -Wall -Wextra \
+		-Winit-self -Wformat -Wformat-nonliteral -Wformat-security \
+		-Wmissing-declarations -Wpointer-arith
+#COMMONCFLAGS += $(WARNINGFLAG)
+
+#Other flags
+SHAREDOBJFLAGS := -shared -Wl,-shared,-Bsymbolic -Wl,--no-undefined
+
+# Always generate debug info. This is stripped from the executable files
+# in the final target image. The size of stripped image with and without -g
+# is the same, so code generation is not affected.
+#COMMONCFLAGS += -g
+
+# Enable optimization: default is very inefficient.
+#COMMONCFLAGS += -Os \
+#		-fomit-frame-pointer \
+#		-fno-strict-aliasing
+
+MRVL_COMMON_INCLUDE = -I$(PXA_APPS_DIR)/include					
+
+PXA_LD_FLAGS = $(LD_FLAGS)
+PXA_LD_FLAGS += -L$(PXA_TARGET_OLIB) \
+		-L$(MRVLDIR)/services/android_wrapper/obj
+
+#start CFLAGS here
+CFLAGS:=
+CFLAGS += -DNOT_DROPPED_FLAGS_TEST
+
+not_droped_flags_test = \
+	echo '$(CFLAGS)' | grep -q NOT_DROPPED_FLAGS_TEST || \
+	(\
+		echo "@@================================================@@"&&\
+		echo NOT_DROPPED_FLAGS_TEST Failed &&\
+		echo It means that $@ file compiled with broken CFLAGS &&\
+		echo Please review related Makefile &&\
+		echo Note that original CFLAGS come from telephony main Makefile &&\
+		echo "@@================================================@@"&&\
+		exit 2 ;\
+	) &&
+
+CFLAGS += $(COMMONCFLAGS)
+CFLAGS += $(MRVL_COMMON_INCLUDE)
+#temp flags to pass build without android
+CFLAGS += -DPROPERTY_VALUE_MAX=4 -DNAME_MAX=81
+
+# Bellow test_cmd_line Rule required for testing compiler lines to always happen
+# i.e. during every make run - we need to test per every object if his CMD line get changed
+.PHONY: test_cmd_line
+
+#	Special rules for forceing linker to always run
+.PHONY: alwayslink
+
+# Rule for copy binary output and strip it from debug info.
+# $(1) - file to be copied
+# $(2) - relative path to output dir to copy to
+# Usage: $(call copy_elf,file,dir)
+#
+# copies file to <out>/symbols/dir
+# strips debug info from file and copies the product into <out>/dir
+# note the --strip-unneeded --discard-locals options are required otherwise
+# .ko produced have no symbols that are required for relocation and linkage with other .ko's
+copy_elf = $(call __copy_elf__,$(strip $(1)),$(strip $(2)))
+
+__copy_elf__ = \
+  $(MRVL_HIDE)echo '\033[1;35m'"Installing $(1)"'\033[0m' && \
+  mkdir -p $(SYMBOLS_DIR)/$(2) $(INSTALL_DIR)/$(2) && \
+  cp -f $(1) $(SYMBOLS_DIR)/$(2) && \
+  cp -f $(1) $(INSTALL_DIR)/$(2) && \
+  $(STRIP) --strip-unneeded --discard-locals $(INSTALL_DIR)/$(2)/$(notdir $(1)) ;
+
+#Rule for simple target clean
+# $(1) - binary to clean (dtarget)
+# $(2) - location in install dir
+clean_target = $(call __clean_target__, $(notdir $(1)), $(strip $(2)))
+
+__clean_target__ = \
+  $(MRVL_HIDE)echo '\033[1;35m'"cleaning $(1)"'\033[0m' && \
+  rm -rf $(SYMBOLS_DIR)/$(2)/$(1) && \
+  rm -rf $(INSTALL_DIR)/$(2)/$(1) && \
+  rm -rf $(LOCAL_BUILD_DIR);
+
+#
+## create generic rule for generation a local build directory.
+## $(1) - name of the local build directory.
+#
+define define-local-build-dir
+$(eval $(call __define-local-build-dir__,$(strip $(1))))
+endef
+
+define __define-local-build-dir__
+LOCAL_BUILD_DIR := $(OBJ_DIR)/$(1)
+$(OBJ_DIR)/$(1):
+	$(MRVL_HIDE)mkdir -p $(OBJ_DIR)/$(1)
+endef
+
+#    Automatic Rules generator for any .c, .cpp, or .S files
+#
+#    User required to define LOCAL_BUILD_DIR prior to calling this function
+#    As well as defining rule for constructing LOCAL_BUILD_DIR
+#    Input parameters:
+#    $(1) - base name of "all results"
+#    $(2) - Source file (.c|.cpp|.S)
+#    $(3) - Extra CFLAGS for this file compilation
+#
+#    Example with explanation:
+#### define directory where the compilation objects will be created
+#    $(eval $(call define-local-build-dir, obj))
+#### Define final result - e.g. executable test_app
+#    dtarget := test_app
+#    all: $(dtarget)
+#### Call to virtual rule creator it will define per object
+#### rules and also fill
+#### test_app_oo with a list of $(LOCAL_BUILD_DIR)/<source_file_name>.o
+#### test_app_ii with a list of $(LOCAL_BUILD_DIR)/<source_file_name>.i (needed for Diag aware applications)
+#### test_app_dd with a list of $(LOCAL_BUILD_DIR)/<source_file_name>.d (for getting build dependencies)
+#    $(eval $(call add-many-objects-rule, test_app , <source files separated by space (' ')>, -D<specific flags>,))
+#    $(dtarget): $(test_app_ii) $(test_app_oo)
+#           $(CC) -o $@ $(test_app_oo)
+###  $(test_app_dd) is a dependency files which we include by Makefile
+#    ifeq "$(filter clean install,$(MAKECMDGOALS))" ""
+#    include $(test_app_dd)
+#    endif
+#
+define add-many-objects-rule
+$(foreach i,$(strip $(2)),$(eval $(call __add-object-rule__,$(strip $(1)),$(i),$(strip $(3)),)))
+endef
+
+define __add-object-rule__
+ifeq "$(suffix $(2))" ".c"
+
+$(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).o.cmd) : $(2) test_cmd_line | $(LOCAL_BUILD_DIR)
+	@echo '$(CC) $(CFLAGS) $(3) -c -o $$(basename $$@).o $$<' | cmp -s - $$@ || \
+	 echo '$(CC) $(CFLAGS) $(3) -c -o $$(basename $$@).o $$<' > $$@;
+
+$(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).o) : $(2) $(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).o.cmd) | $(LOCAL_BUILD_DIR)
+	@echo "  CC     $$< "
+	$(MRVL_HIDE)$(not_droped_flags_test)$(CC) $(CFLAGS) $(3) -c -o $$@ $$<
+
+$(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).i.cmd) : $(2) test_cmd_line | $(LOCAL_BUILD_DIR)
+	@echo '$(CC) $(CFLAGS) $(3) -C -E -o $$(basename $$@).i $$<' | cmp -s - $$@ || \
+	 echo '$(CC) $(CFLAGS) $(3) -C -E -o $$(basename $$@).i $$<' > $$@
+
+$(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).i) : $(2) $(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).i.cmd) | $(LOCAL_BUILD_DIR)
+	@echo "  II     $$@"
+	$(MRVL_HIDE)$(not_droped_flags_test)$(CC) $(CFLAGS) -DDIAG_API_H $(3) -C -E -o $$@ $$<
+
+$(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).d) : $(2) | $(LOCAL_BUILD_DIR)
+	@echo "  DD     $$@"
+	$(MRVL_HIDE)set -e; rm -f $$@ 2>&- || true ;\
+		$(CC) -M $(CFLAGS) $(3)  $$<  > $$@.temp; \
+		awk '{gsub(/([^:]*:)/,"$$(@:.d=.o) $$(@:.d=.i) $$@ : ",$$$$0); print $$$$0}' > $$@ < $$@.temp ;\
+		rm $$@.temp 2>&- || true
+
+endif
+ifeq "$(suffix $(2))" ".cpp"
+$(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).o.cmd) : $(2) test_cmd_line | $(LOCAL_BUILD_DIR)
+	@echo '$(CPP) $(CFLAGS) $(3) -c -o $$(basename $$@).o $$<' | cmp -s - $$@ || \
+	 echo '$(CPP) $(CFLAGS) $(3) -c -o $$(basename $$@).o $$<' > $$@
+
+$(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).o) : $(2) $(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).o.cmd) | $(LOCAL_BUILD_DIR)
+	@echo "  CPP     $$<"
+	$(MRVL_HIDE)$(not_droped_flags_test)$(CPP) $(CFLAGS) $(3) -c -o $$@ $$<
+
+$(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).i.cmd) : $(2) test_cmd_line | $(LOCAL_BUILD_DIR)
+	@echo '$(CPP) $(CFLAGS) $(3) -C -E -o $$(basename $$@).i $$<' | cmp -s - $$@ || \
+	 echo '$(CPP) $(CFLAGS) $(3) -C -E -o $$(basename $$@).i $$<' > $$@
+
+$(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).i) : $(2) $(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).i.cmd) | $(LOCAL_BUILD_DIR)
+	@echo "  II     $$@"
+	$(MRVL_HIDE)$(not_droped_flags_test)$(CPP) $(CFLAGS) -DDIAG_API_H $(3) -C -E -o $$@ $$<
+
+$(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).d) : $(2) | $(LOCAL_BUILD_DIR)
+	@echo "  DD     $$@"
+	$(MRVL_HIDE)set -e; rm -f $$@ 2>&- || true ;\
+		$(CPP) -M $(CFLAGS) $(3)  $$<  > $$@.temp; \
+		awk '{gsub(/([^:]*:)/,"$$(@:.d=.o) $$(@:.d=.i) $$@ : ",$$$$0); print $$$$0}' > $$@ < $$@.temp ;\
+		rm $$@.temp 2>&- || true
+endif
+ifeq "$(suffix $(2))" ".S"
+$(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).o.cmd) : $(2) test_cmd_line | $(LOCAL_BUILD_DIR)
+	@echo '$(AS) $(AFLAGS) -o $$(basename $$@).i $$<' | cmp -s - $$@ || \
+	 echo '$(AS) $(AFLAGS) -o $$(basename $$@).i $$<' > $$@
+
+$(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).o) : $(2) $(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).o.cmd) | $(LOCAL_BUILD_DIR)
+	@echo "  AS     $$<"
+	$(MRVL_HIDE)$(AS) $(AFLAGS) -o $$@ $$<
+endif
+
+$(1)_oo += $(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).o)
+##
+## No need to accumulate .i or .d files for assembler input
+##
+ifneq "$(suffix $(2))" ".S"
+$(1)_ii += $(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).i)
+$(1)_dd += $(LOCAL_BUILD_DIR)/$(notdir $(basename $(2)).d)
+endif
+
+endef
+#end Automatic Rules generator
diff --git a/package/network/utils/iptables/Makefile b/package/network/utils/iptables/Makefile
new file mode 100644
index 0000000..e8cbd5d
--- /dev/null
+++ b/package/network/utils/iptables/Makefile
@@ -0,0 +1,690 @@
+#
+# Copyright (C) 2006-2016 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.8.7
+PKG_RELEASE:=2
+
+PKG_SOURCE_URL:=https://netfilter.org/projects/iptables/files
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_HASH:=c109c96bb04998cd44156622d36f8e04b140701ec60531a10668cfdff5e8d8f0
+
+PKG_FIXUP:=autoreconf
+PKG_FLAGS:=nonshared
+
+PKG_INSTALL:=1
+PKG_BUILD_FLAGS:=gc-sections no-lto
+PKG_BUILD_PARALLEL:=1
+PKG_LICENSE:=GPL-2.0
+PKG_CPE_ID:=cpe:/a:netfilter:iptables
+
+include $(INCLUDE_DIR)/package.mk
+ifeq ($(DUMP),)
+  -include $(LINUX_DIR)/.config
+  include $(INCLUDE_DIR)/netfilter.mk
+  STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell grep 'NETFILTER' $(LINUX_DIR)/.config | $(MKHASH) md5)
+endif
+
+
+define Package/iptables/Default
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=Firewall
+  URL:=https://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+= +(!MODULE_BUILDIN):kmod-ipt-core +libip4tc +IPV6:libip6tc +libxtables
+endef
+
+define Package/iptables/config
+  config IPTABLES_CONNLABEL
+	bool "Enable Connlabel support"
+	default n
+	help
+		This enable connlabel support in iptables.
+
+  config IPTABLES_NFTABLES
+	bool "Enable Nftables support"
+	default n
+	help
+		This enable nftables support in iptables.
+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
+  - FLOWOFFLOAD
+  - LOG
+  - MARK
+  - MASQUERADE
+  - REDIRECT
+  - SET
+  - SNAT
+  - TCPMSS
+
+ Tables:
+  - filter
+  - mangle
+  - nat
+  - raw
+
+endef
+
+define Package/iptables-nft
+$(call Package/iptables/Default)
+  TITLE:=IP firewall administration tool nft
+  DEPENDS:=iptables @IPTABLES_NFTABLES +libxtables-nft
+endef
+
+define Package/iptables-nft/description
+Extra iptables nftables nft binaries.
+  iptables-nft
+  iptables-nft-restore
+  iptables-nft-save
+  iptables-translate
+  iptables-restore-translate
+endef
+
+define Package/iptables-mod-conntrack-extra
+$(call Package/iptables/Module, +kmod-ipt-conntrack-extra +kmod-ipt-raw)
+  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-conntrack-label
+$(call Package/iptables/Module, +kmod-ipt-conntrack-label @IPTABLES_CONNLABEL)
+  TITLE:=Connection tracking labeling extension
+  DEFAULT:=y if IPTABLES_CONNLABEL
+endef
+
+define Package/iptables-mod-conntrack-label/description
+Match and set label(s) on connection tracking entries
+
+ Matches:
+  - connlabel
+
+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
+  - bpf
+
+endef
+
+define Package/iptables-mod-ipopt
+$(call Package/iptables/Module, +(!MODULE_BUILDIN):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-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-trace
+$(call Package/iptables/Module, +kmod-ipt-debug)
+  TITLE:=Netfilter TRACE target
+endef
+
+define Package/iptables-mod-trace/description
+ iptables extension for TRACE target
+
+ Includes:
+  - libxt_TRACE
+
+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-rpfilter
+$(call Package/iptables/Module, +kmod-ipt-rpfilter)
+  TITLE:=rpfilter iptables extension
+endef
+
+define Package/iptables-mod-rpfilter/description
+iptables extensions for reverse path filter test on a packet
+
+ Matches:
+  - rpfilter
+
+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
+  - pkttype
+  - quota
+
+endef
+
+define Package/iptables-mod-physdev
+$(call Package/iptables/Module, +kmod-ipt-physdev)
+  TITLE:=physdev iptables extension
+endef
+
+define Package/iptables-mod-physdev/description
+The iptables physdev match.
+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-socket
+$(call Package/iptables/Module, +kmod-ipt-socket)
+  TITLE:=Socket match iptables extensions
+endef
+
+define Package/iptables-mod-socket/description
+Socket match iptables extensions.
+
+ Matches:
+  - socket
+
+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.
+
+ 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/iptables-mod-checksum
+$(call Package/iptables/Module, +kmod-ipt-checksum)
+  TITLE:=IP CHECKSUM target extension
+endef
+
+define Package/iptables-mod-checksum/description
+iptables extension for the CHECKSUM calculation target
+endef
+
+define Package/ip6tables
+$(call Package/iptables/Default)
+  DEPENDS:=@IPV6 +(!MODULE_BUILDIN):kmod-ip6tables +iptables
+  CATEGORY:=Network
+  TITLE:=IPv6 firewall administration tool
+  MENU:=1
+endef
+
+define Package/ip6tables-nft
+$(call Package/iptables/Default)
+  DEPENDS:=ip6tables @IPTABLES_NFTABLES +libxtables-nft
+  TITLE:=IP firewall administration tool nft
+endef
+
+define Package/ip6tables-nft/description
+Extra ip6tables nftables nft binaries.
+  iptables-nft
+  iptables-nft-restore
+  iptables-nft-save
+  iptables-translate
+  iptables-restore-translate
+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/libip4tc
+$(call Package/iptables/Default)
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE:=IPv4 firewall - shared libiptc library
+  ABI_VERSION:=2
+  DEPENDS:=+libxtables
+endef
+
+define Package/libip6tc
+$(call Package/iptables/Default)
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE:=IPv6 firewall - shared libiptc library
+  ABI_VERSION:=2
+  DEPENDS:=+libxtables
+endef
+
+define Package/libxtables
+ $(call Package/iptables/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=IPv4/IPv6 firewall - shared xtables library
+ ABI_VERSION:=12
+ DEPENDS:= \
+	+IPTABLES_CONNLABEL:libnetfilter-conntrack \
+	+IPTABLES_NFTABLES:libnftnl
+endef
+
+define Package/libxtables-nft
+ $(call Package/iptables/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=IPv4/IPv6 firewall - shared xtables nft library
+ ABI_VERSION:=12
+ DEPENDS:=libxtables
+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-static \
+	--enable-devel \
+	--with-kernel="$(LINUX_DIR)/user_headers" \
+	--with-xtlibdir=/usr/lib/iptables \
+	--with-xt-lock-name=/var/run/xtables.lock \
+	$(if $(CONFIG_IPTABLES_CONNLABEL),,--disable-connlabel) \
+	$(if $(CONFIG_IPTABLES_NFTABLES),,--disable-nftables) \
+	$(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))))"
+
+ifneq ($(wildcard $(PKG_BUILD_DIR)/.config_*),$(subst .configured_,.config_,$(STAMP_CONFIGURED)))
+  define Build/Configure/rebuild
+	$(FIND) $(PKG_BUILD_DIR) -name \*.o -or -name \*.\?o -or -name \*.a | $(XARGS) rm -f
+	rm -f $(PKG_BUILD_DIR)/.config_*
+	rm -f $(PKG_BUILD_DIR)/.configured_*
+	touch $(subst .configured_,.config_,$(STAMP_CONFIGURED))
+  endef
+endif
+
+define Build/Configure
+$(Build/Configure/rebuild)
+$(Build/Configure/Default)
+endef
+
+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-legacy-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/iptables-nft/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(CP) $(PKG_INSTALL_DIR)/usr/sbin/xtables-nft-multi $(1)/usr/sbin/
+	$(CP) $(PKG_INSTALL_DIR)/usr/sbin/iptables-nft{,-restore,-save} $(1)/usr/sbin/
+	$(CP) $(PKG_INSTALL_DIR)/usr/sbin/iptables{,-restore}-translate $(1)/usr/sbin/
+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/ip6tables-nft/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(CP) $(PKG_INSTALL_DIR)/usr/sbin/ip6tables-nft{,-restore,-save} $(1)/usr/sbin/
+	$(CP) $(PKG_INSTALL_DIR)/usr/sbin/ip6tables{,-restore}-translate $(1)/usr/sbin/
+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 Package/libxtables-nft/install
+	$(INSTALL_DIR) $(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,libxtables))
+$(eval $(call BuildPackage,libxtables-nft))
+$(eval $(call BuildPackage,libip4tc))
+$(eval $(call BuildPackage,libip6tc))
+$(eval $(call BuildPackage,iptables))
+$(eval $(call BuildPackage,iptables-nft))
+$(eval $(call BuildPlugin,iptables-mod-conntrack-extra,$(IPT_CONNTRACK_EXTRA-m)))
+$(eval $(call BuildPlugin,iptables-mod-conntrack-label,$(IPT_CONNTRACK_LABEL-m)))
+$(eval $(call BuildPlugin,iptables-mod-extra,$(IPT_EXTRA-m)))
+$(eval $(call BuildPlugin,iptables-mod-physdev,$(IPT_PHYSDEV-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-hashlimit,$(IPT_HASHLIMIT-m)))
+$(eval $(call BuildPlugin,iptables-mod-rpfilter,$(IPT_RPFILTER-m)))
+$(eval $(call BuildPlugin,iptables-mod-led,$(IPT_LED-m)))
+$(eval $(call BuildPlugin,iptables-mod-socket,$(IPT_SOCKET-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-trace,$(IPT_DEBUG-m)))
+$(eval $(call BuildPlugin,iptables-mod-nfqueue,$(IPT_NFQUEUE-m)))
+$(eval $(call BuildPlugin,iptables-mod-checksum,$(IPT_CHECKSUM-m)))
+$(eval $(call BuildPackage,ip6tables))
+$(eval $(call BuildPackage,ip6tables-nft))
+$(eval $(call BuildPlugin,ip6tables-extra,$(IPT_IPV6_EXTRA-m)))
+$(eval $(call BuildPlugin,ip6tables-mod-nat,$(IPT_NAT6-m)))
+
diff --git a/package/network/utils/iptables/patches/010-add-set-dscpmark-support.patch b/package/network/utils/iptables/patches/010-add-set-dscpmark-support.patch
new file mode 100644
index 0000000..9a5de63
--- /dev/null
+++ b/package/network/utils/iptables/patches/010-add-set-dscpmark-support.patch
@@ -0,0 +1,452 @@
+From 74267bacce0c43e5038b0377cb7c08f1ad9d50a3 Mon Sep 17 00:00:00 2001
+From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
+Date: Sat, 23 Mar 2019 10:21:03 +0000
+Subject: [PATCH] iptables: connmark - add set-dscpmark option for openwrt
+
+Naive user space front end to xt_connmark 'setdscp' option.
+
+iptables -A QOS_MARK_eth0 -t mangle -j CONNMARK --set-dscpmark 0xfc000000/0x01000000
+
+This version has a hack to support a backport to 4.14
+
+Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
+---
+ extensions/libxt_CONNMARK.c           | 315 +++++++++++++++++++++++++-
+ include/linux/netfilter/xt_connmark.h |  10 +
+ 2 files changed, 324 insertions(+), 1 deletion(-)
+
+--- a/extensions/libxt_CONNMARK.c
++++ b/extensions/libxt_CONNMARK.c
+@@ -22,6 +22,7 @@
+ #include <stdbool.h>
+ #include <stdint.h>
+ #include <stdio.h>
++#include <strings.h>
+ #include <xtables.h>
+ #include <linux/netfilter/xt_CONNMARK.h>
+ 
+@@ -49,6 +50,7 @@ enum {
+ 	O_CTMASK,
+ 	O_NFMASK,
+ 	O_MASK,
++	O_DSCP_MARK,
+ 	F_SET_MARK         = 1 << O_SET_MARK,
+ 	F_SAVE_MARK        = 1 << O_SAVE_MARK,
+ 	F_RESTORE_MARK     = 1 << O_RESTORE_MARK,
+@@ -61,8 +63,10 @@ enum {
+ 	F_CTMASK           = 1 << O_CTMASK,
+ 	F_NFMASK           = 1 << O_NFMASK,
+ 	F_MASK             = 1 << O_MASK,
++	F_DSCP_MARK	   = 1 << O_DSCP_MARK,
+ 	F_OP_ANY           = F_SET_MARK | F_SAVE_MARK | F_RESTORE_MARK |
+-	                     F_AND_MARK | F_OR_MARK | F_XOR_MARK | F_SET_XMARK,
++	                     F_AND_MARK | F_OR_MARK | F_XOR_MARK | F_SET_XMARK |
++			     F_DSCP_MARK,
+ };
+ 
+ static const char *const xt_connmark_shift_ops[] = {
+@@ -114,6 +118,8 @@ static const struct xt_option_entry conn
+ 	 .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, nfmask)},
+ 	{.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32,
+ 	 .excl = F_CTMASK | F_NFMASK},
++	{.name = "set-dscpmark", .id = O_DSCP_MARK, .type = XTTYPE_MARKMASK32,
++	 .excl = F_OP_ANY},
+ 	XTOPT_TABLEEND,
+ };
+ #undef s
+@@ -148,6 +154,38 @@ static const struct xt_option_entry conn
+ };
+ #undef s
+ 
++#define s struct xt_connmark_tginfo3
++static const struct xt_option_entry connmark_tg_opts_v3[] = {
++	{.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32,
++	 .excl = F_OP_ANY},
++	{.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
++	 .excl = F_OP_ANY},
++	{.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
++	 .excl = F_OP_ANY},
++	{.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
++	 .excl = F_OP_ANY},
++	{.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
++	 .excl = F_OP_ANY},
++	{.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE,
++	 .excl = F_OP_ANY},
++	{.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
++	 .excl = F_OP_ANY},
++	{.name = "left-shift-mark", .id = O_LEFT_SHIFT_MARK, .type = XTTYPE_UINT8,
++	 .min = 0, .max = 32},
++	{.name = "right-shift-mark", .id = O_RIGHT_SHIFT_MARK, .type = XTTYPE_UINT8,
++	 .min = 0, .max = 32},
++	{.name = "ctmask", .id = O_CTMASK, .type = XTTYPE_UINT32,
++	 .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, ctmask)},
++	{.name = "nfmask", .id = O_NFMASK, .type = XTTYPE_UINT32,
++	 .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, nfmask)},
++	{.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32,
++	 .excl = F_CTMASK | F_NFMASK},
++	{.name = "set-dscpmark", .id = O_DSCP_MARK, .type = XTTYPE_MARKMASK32,
++	 .excl = F_OP_ANY},
++	XTOPT_TABLEEND,
++};
++#undef s
++
+ static void connmark_tg_help(void)
+ {
+ 	printf(
+@@ -175,6 +213,15 @@ static void connmark_tg_help_v2(void)
+ );
+ }
+ 
++static void connmark_tg_help_v3(void)
++{
++	connmark_tg_help_v2();
++	printf(
++"  --set-dscpmark value/mask        Save DSCP to conntrack mark value\n"
++);
++}
++
++
+ static void connmark_tg_init(struct xt_entry_target *target)
+ {
+ 	struct xt_connmark_tginfo1 *info = (void *)target->data;
+@@ -199,6 +246,16 @@ static void connmark_tg_init_v2(struct x
+ 	info->shift_bits = 0;
+ }
+ 
++static void connmark_tg_init_v3(struct xt_entry_target *target)
++{
++	struct xt_connmark_tginfo3 *info;
++
++	connmark_tg_init_v2(target);
++	info = (void *)target->data;
++
++	info->func = 0;
++}
++
+ static void CONNMARK_parse(struct xt_option_call *cb)
+ {
+ 	struct xt_connmark_target_info *markinfo = cb->data;
+@@ -253,6 +310,23 @@ static void connmark_tg_parse(struct xt_
+ 		info->ctmark = cb->val.u32;
+ 		info->ctmask = 0;
+ 		break;
++	case O_DSCP_MARK:
++/* we sneaky sneaky this.  nfmask isn't used by the set mark functionality
++ * and by default is set to uint32max.  We can use the top bit as a flag
++ * that we're in DSCP_MARK submode of SET_MARK, if set then it's normal
++ * if unset then we're in DSCP_MARK
++ */
++		info->mode   = XT_CONNMARK_SET;
++		info->ctmark = cb->val.mark;
++		info->ctmask = cb->val.mask;
++		info->nfmask = info->ctmark ? ffs(info->ctmark) - 1 : 0;
++		/* need 6 contiguous bits */
++		if ((~0 & (info->ctmark >> info->nfmask)) != 0x3f)
++			xtables_error(PARAMETER_PROBLEM,
++				"CONNMARK set-dscpmark: need 6 contiguous dscpmask bits");
++		if (info->ctmark & info->ctmask)
++			xtables_error(PARAMETER_PROBLEM,
++				"CONNMARK set-dscpmark: dscpmask/statemask bits overlap");
+ 	case O_SAVE_MARK:
+ 		info->mode = XT_CONNMARK_SAVE;
+ 		break;
+@@ -320,6 +394,78 @@ static void connmark_tg_parse_v2(struct
+ 	}
+ }
+ 
++static void connmark_tg_parse_v3(struct xt_option_call *cb)
++{
++	struct xt_connmark_tginfo3 *info = cb->data;
++
++	xtables_option_parse(cb);
++	switch (cb->entry->id) {
++	case O_SET_XMARK:
++		info->mode   = XT_CONNMARK_SET;
++		info->func   = XT_CONNMARK_VALUE;
++		info->ctmark = cb->val.mark;
++		info->ctmask = cb->val.mask;
++		break;
++	case O_SET_MARK:
++		info->mode   = XT_CONNMARK_SET;
++		info->func   = XT_CONNMARK_VALUE;
++		info->ctmark = cb->val.mark;
++		info->ctmask = cb->val.mark | cb->val.mask;
++		break;
++	case O_AND_MARK:
++		info->mode   = XT_CONNMARK_SET;
++		info->func   = XT_CONNMARK_VALUE;
++		info->ctmark = 0;
++		info->ctmask = ~cb->val.u32;
++		break;
++	case O_OR_MARK:
++		info->mode   = XT_CONNMARK_SET;
++		info->func   = XT_CONNMARK_VALUE;
++		info->ctmark = cb->val.u32;
++		info->ctmask = cb->val.u32;
++		break;
++	case O_XOR_MARK:
++		info->mode   = XT_CONNMARK_SET;
++		info->func   = XT_CONNMARK_VALUE;
++		info->ctmark = cb->val.u32;
++		info->ctmask = 0;
++		break;
++	case O_DSCP_MARK:
++		info->mode   = XT_CONNMARK_SET;
++		info->func   = XT_CONNMARK_DSCP;
++		info->ctmark = cb->val.mark;
++		info->ctmask = cb->val.mask;
++		info->shift_bits = info->ctmark ? ffs(info->ctmark) - 1 : 0;
++		/* need 6 contiguous bits */
++		if ((~0 & (info->ctmark >> info->shift_bits)) != 0x3f)
++			xtables_error(PARAMETER_PROBLEM,
++				"CONNMARK set-dscpmark: need 6 contiguous dscpmask bits");
++		if (info->ctmark & info->ctmask)
++			xtables_error(PARAMETER_PROBLEM,
++				"CONNMARK set-dscpmark: dscpmask/statemask bits overlap");
++		break;
++	case O_SAVE_MARK:
++		info->mode = XT_CONNMARK_SAVE;
++		break;
++	case O_RESTORE_MARK:
++		info->mode = XT_CONNMARK_RESTORE;
++		break;
++	case O_MASK:
++		info->nfmask = info->ctmask = cb->val.u32;
++		break;
++	case O_LEFT_SHIFT_MARK:
++		info->shift_dir = D_SHIFT_LEFT;
++		info->shift_bits = cb->val.u8;
++		break;
++	case O_RIGHT_SHIFT_MARK:
++		info->shift_dir = D_SHIFT_RIGHT;
++		info->shift_bits = cb->val.u8;
++		break;
++	default:
++		break;
++	}
++}
++
+ static void connmark_tg_check(struct xt_fcheck_call *cb)
+ {
+ 	if (!(cb->xflags & F_OP_ANY))
+@@ -463,6 +609,65 @@ connmark_tg_print_v2(const void *ip, con
+ 	}
+ }
+ 
++static void
++connmark_tg_print_v3(const void *ip, const struct xt_entry_target *target,
++                  int numeric)
++{
++	const struct xt_connmark_tginfo3 *info = (const void *)target->data;
++	const char *shift_op = xt_connmark_shift_ops[info->shift_dir];
++
++	switch (info->mode) {
++	case XT_CONNMARK_SET:
++		if (info->func & XT_CONNMARK_DSCP) {
++			printf(" CONNMARK DSCP 0x%x/0x%x",
++			       info->ctmark, info->ctmask);
++		}
++		if (info->func & XT_CONNMARK_VALUE) {
++			if (info->ctmark == 0)
++				printf(" CONNMARK and 0x%x",
++				       (unsigned int)(uint32_t)~info->ctmask);
++			else if (info->ctmark == info->ctmask)
++				printf(" CONNMARK or 0x%x", info->ctmark);
++			else if (info->ctmask == 0)
++				printf(" CONNMARK xor 0x%x", info->ctmark);
++			else if (info->ctmask == 0xFFFFFFFFU)
++				printf(" CONNMARK set 0x%x", info->ctmark);
++			else
++				printf(" CONNMARK xset 0x%x/0x%x",
++				       info->ctmark, info->ctmask);
++		}
++		break;
++	case XT_CONNMARK_SAVE:
++		if (info->nfmask == UINT32_MAX && info->ctmask == UINT32_MAX)
++			printf(" CONNMARK save");
++		else if (info->nfmask == info->ctmask)
++			printf(" CONNMARK save mask 0x%x", info->nfmask);
++		else
++			printf(" CONNMARK save nfmask 0x%x ctmask ~0x%x",
++			       info->nfmask, info->ctmask);
++		break;
++	case XT_CONNMARK_RESTORE:
++		if (info->ctmask == UINT32_MAX && info->nfmask == UINT32_MAX)
++			printf(" CONNMARK restore");
++		else if (info->ctmask == info->nfmask)
++			printf(" CONNMARK restore mask 0x%x", info->ctmask);
++		else
++			printf(" CONNMARK restore ctmask 0x%x nfmask ~0x%x",
++			       info->ctmask, info->nfmask);
++		break;
++
++	default:
++		printf(" ERROR: UNKNOWN CONNMARK MODE");
++		break;
++	}
++
++	if (info->mode <= XT_CONNMARK_RESTORE &&
++	    !(info->mode == XT_CONNMARK_SET && info->func == XT_CONNMARK_DSCP) &&
++	    info->shift_bits != 0) {
++		printf(" %s %u", shift_op, info->shift_bits);
++	}
++}
++
+ static void CONNMARK_save(const void *ip, const struct xt_entry_target *target)
+ {
+ 	const struct xt_connmark_target_info *markinfo =
+@@ -548,6 +753,38 @@ connmark_tg_save_v2(const void *ip, cons
+ 	}
+ }
+ 
++static void
++connmark_tg_save_v3(const void *ip, const struct xt_entry_target *target)
++{
++	const struct xt_connmark_tginfo3 *info = (const void *)target->data;
++	const char *shift_op = xt_connmark_shift_ops[info->shift_dir];
++
++	switch (info->mode) {
++	case XT_CONNMARK_SET:
++		if (info->func & XT_CONNMARK_VALUE)
++			printf(" --set-xmark 0x%x/0x%x", info->ctmark, info->ctmask);
++		if (info->func & XT_CONNMARK_DSCP)
++			printf(" --set-dscpmark 0x%x/0x%x", info->ctmark, info->ctmask);
++		break;
++	case XT_CONNMARK_SAVE:
++		printf(" --save-mark --nfmask 0x%x --ctmask 0x%x",
++		       info->nfmask, info->ctmask);
++		break;
++	case XT_CONNMARK_RESTORE:
++		printf(" --restore-mark --nfmask 0x%x --ctmask 0x%x",
++		       info->nfmask, info->ctmask);
++		break;
++	default:
++		printf(" ERROR: UNKNOWN CONNMARK MODE");
++		break;
++	}
++	if (info->mode <= XT_CONNMARK_RESTORE &&
++	    !(info->mode == XT_CONNMARK_SET && info->func == XT_CONNMARK_DSCP) &&
++	    info->shift_bits != 0) {
++		printf(" --%s %u", shift_op, info->shift_bits);
++	}
++}
++
+ static int connmark_tg_xlate(struct xt_xlate *xl,
+ 			     const struct xt_xlate_tg_params *params)
+ {
+@@ -639,6 +876,66 @@ static int connmark_tg_xlate_v2(struct x
+ 
+ 	return 1;
+ }
++
++static int connmark_tg_xlate_v3(struct xt_xlate *xl,
++			     const struct xt_xlate_tg_params *params)
++{
++	const struct xt_connmark_tginfo3 *info =
++		(const void *)params->target->data;
++	const char *shift_op = xt_connmark_shift_ops[info->shift_dir];
++
++	switch (info->mode) {
++	case XT_CONNMARK_SET:
++		xt_xlate_add(xl, "ct mark set ");
++		if (info->func & XT_CONNMARK_VALUE) {
++			if (info->ctmask == 0xFFFFFFFFU)
++				xt_xlate_add(xl, "0x%x ", info->ctmark);
++			else if (info->ctmark == 0)
++				xt_xlate_add(xl, "ct mark and 0x%x", ~info->ctmask);
++			else if (info->ctmark == info->ctmask)
++				xt_xlate_add(xl, "ct mark or 0x%x",
++					     info->ctmark);
++			else if (info->ctmask == 0)
++				xt_xlate_add(xl, "ct mark xor 0x%x",
++					     info->ctmark);
++			else
++				xt_xlate_add(xl, "ct mark xor 0x%x and 0x%x",
++					     info->ctmark, ~info->ctmask);
++		}
++		if (info->func & XT_CONNMARK_DSCP) {
++/* FIXME the nftables syntax would go here if only we knew what it was */
++			xt_xlate_add(xl, "ct mark set typeof(ct mark) ip dscp "
++					 "<< %u or 0x%x", info->shift_bits,
++					     info->ctmask);
++		}
++		break;
++	case XT_CONNMARK_SAVE:
++		xt_xlate_add(xl, "ct mark set mark");
++		if (!(info->nfmask == UINT32_MAX &&
++		    info->ctmask == UINT32_MAX)) {
++			if (info->nfmask == info->ctmask)
++				xt_xlate_add(xl, " and 0x%x", info->nfmask);
++		}
++		break;
++	case XT_CONNMARK_RESTORE:
++		xt_xlate_add(xl, "meta mark set ct mark");
++		if (!(info->nfmask == UINT32_MAX &&
++		    info->ctmask == UINT32_MAX)) {
++			if (info->nfmask == info->ctmask)
++				xt_xlate_add(xl, " and 0x%x", info->nfmask);
++		}
++		break;
++	}
++
++	if (info->mode <= XT_CONNMARK_RESTORE &&
++	    !(info->mode == XT_CONNMARK_SET && info->func == XT_CONNMARK_DSCP) &&
++	    info->shift_bits != 0) {
++		xt_xlate_add(xl, " %s %u", shift_op, info->shift_bits);
++	}
++
++	return 1;
++}
++
+ static struct xtables_target connmark_tg_reg[] = {
+ 	{
+ 		.family        = NFPROTO_UNSPEC,
+@@ -687,6 +984,22 @@ static struct xtables_target connmark_tg
+ 		.x6_options    = connmark_tg_opts_v2,
+ 		.xlate         = connmark_tg_xlate_v2,
+ 	},
++	{
++		.version       = XTABLES_VERSION,
++		.name          = "CONNMARK",
++		.revision      = 3,
++		.family        = NFPROTO_UNSPEC,
++		.size          = XT_ALIGN(sizeof(struct xt_connmark_tginfo3)),
++		.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo3)),
++		.help          = connmark_tg_help_v3,
++		.init          = connmark_tg_init_v3,
++		.print         = connmark_tg_print_v3,
++		.save          = connmark_tg_save_v3,
++		.x6_parse      = connmark_tg_parse_v3,
++		.x6_fcheck     = connmark_tg_check,
++		.x6_options    = connmark_tg_opts_v3,
++		.xlate         = connmark_tg_xlate_v3,
++	},
+ };
+ 
+ void _init(void)
+--- a/include/linux/netfilter/xt_connmark.h
++++ b/include/linux/netfilter/xt_connmark.h
+@@ -18,6 +18,11 @@ enum {
+ 	XT_CONNMARK_RESTORE
+ };
+ 
++enum {
++	XT_CONNMARK_VALUE	= (1 << 0),
++	XT_CONNMARK_DSCP	= (1 << 1)
++};
++
+ struct xt_connmark_tginfo1 {
+ 	__u32 ctmark, ctmask, nfmask;
+ 	__u8 mode;
+@@ -28,6 +33,11 @@ struct xt_connmark_tginfo2 {
+ 	__u8 shift_dir, shift_bits, mode;
+ };
+ 
++struct xt_connmark_tginfo3 {
++	__u32 ctmark, ctmask, nfmask;
++	__u8 shift_dir, shift_bits, mode, func;
++};
++
+ struct xt_connmark_mtinfo1 {
+ 	__u32 mark, mask;
+ 	__u8 invert;
diff --git a/package/network/utils/iptables/patches/101-remove-check-already.patch b/package/network/utils/iptables/patches/101-remove-check-already.patch
new file mode 100644
index 0000000..16afafe
--- /dev/null
+++ b/package/network/utils/iptables/patches/101-remove-check-already.patch
@@ -0,0 +1,28 @@
+--- a/libxtables/xtables.c
++++ b/libxtables/xtables.c
+@@ -968,12 +968,6 @@ void xtables_register_match(struct xtabl
+ 	struct xtables_match **pos;
+ 	bool seen_myself = false;
+ 
+-	if (me->next) {
+-		fprintf(stderr, "%s: match \"%s\" already registered\n",
+-			xt_params->program_name, me->name);
+-		exit(1);
+-	}
+-
+ 	if (me->version == NULL) {
+ 		fprintf(stderr, "%s: match %s<%u> is missing a version\n",
+ 		        xt_params->program_name, me->name, me->revision);
+@@ -1152,12 +1146,6 @@ void xtables_register_target(struct xtab
+ 	struct xtables_target **pos;
+ 	bool seen_myself = false;
+ 
+-	if (me->next) {
+-		fprintf(stderr, "%s: target \"%s\" already registered\n",
+-			xt_params->program_name, me->name);
+-		exit(1);
+-	}
+-
+ 	if (me->version == NULL) {
+ 		fprintf(stderr, "%s: target %s<%u> is missing a version\n",
+ 		        xt_params->program_name, me->name, me->revision);
diff --git a/package/network/utils/iptables/patches/102-iptables-disable-modprobe.patch b/package/network/utils/iptables/patches/102-iptables-disable-modprobe.patch
new file mode 100644
index 0000000..b8e19c7
--- /dev/null
+++ b/package/network/utils/iptables/patches/102-iptables-disable-modprobe.patch
@@ -0,0 +1,18 @@
+--- a/libxtables/xtables.c
++++ b/libxtables/xtables.c
+@@ -403,6 +403,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;
+@@ -437,6 +438,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/103-optional-xml.patch b/package/network/utils/iptables/patches/103-optional-xml.patch
new file mode 100644
index 0000000..342808a
--- /dev/null
+++ b/package/network/utils/iptables/patches/103-optional-xml.patch
@@ -0,0 +1,13 @@
+--- a/iptables/xtables-legacy-multi.c
++++ b/iptables/xtables-legacy-multi.c
+@@ -32,8 +32,10 @@ static const struct subcommand multi_sub
+ 
+ 
+ #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/200-configurable_builtin.patch b/package/network/utils/iptables/patches/200-configurable_builtin.patch
new file mode 100644
index 0000000..6d7b5b5
--- /dev/null
+++ b/package/network/utils/iptables/patches/200-configurable_builtin.patch
@@ -0,0 +1,79 @@
+--- a/extensions/GNUmakefile.in
++++ b/extensions/GNUmakefile.in
+@@ -50,11 +50,31 @@ pfb_build_mod := $(filter-out @blacklist
+ pfa_build_mod := $(filter-out @blacklist_modules@ @blacklist_a_modules@,${pfa_build_mod})
+ pf4_build_mod := $(filter-out @blacklist_modules@ @blacklist_4_modules@,${pf4_build_mod})
+ pf6_build_mod := $(filter-out @blacklist_modules@ @blacklist_6_modules@,${pf6_build_mod})
+-pfx_objs      := $(patsubst %,libxt_%.o,${pfx_build_mod})
+-pfb_objs      := $(patsubst %,libebt_%.o,${pfb_build_mod})
+-pfa_objs      := $(patsubst %,libarpt_%.o,${pfa_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})
++pfb_build_static := $(filter $(BUILTIN_MODULES),${pfb_build_mod})
++pfa_build_static := $(filter $(BUILTIN_MODULES),${pfa_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@ pfb_build_static := $(pfb_build_mod)
++@ENABLE_STATIC_TRUE@ pfa_build_static := $(pfa_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))
++pfb_build_mod := $(filter-out $(pfb_build_static),$(pfb_build_mod))
++pfa_build_mod := $(filter-out $(pfa_build_static),$(pfa_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})
++pfb_objs      := $(patsubst %,libebt_%.o,${pfb_build_static})
++pfa_objs      := $(patsubst %,libarpt_%.o,${pfa_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})
+ pfb_solibs    := $(patsubst %,libebt_%.so,${pfb_build_mod})
+ pfa_solibs    := $(patsubst %,libarpt_%.so,${pfa_build_mod})
+@@ -68,14 +88,14 @@ pfx_symlink_files := $(patsubst %,libxt_
+ #
+ targets := libext.a libext4.a libext6.a libext_ebt.a libext_arpt.a matches.man targets.man
+ targets_install :=
+-@ENABLE_STATIC_TRUE@ libext_objs := ${pfx_objs}
+-@ENABLE_STATIC_TRUE@ libext_ebt_objs := ${pfb_objs}
+-@ENABLE_STATIC_TRUE@ libext_arpt_objs := ${pfa_objs}
+-@ENABLE_STATIC_TRUE@ libext4_objs := ${pf4_objs}
+-@ENABLE_STATIC_TRUE@ libext6_objs := ${pf6_objs}
+-@ENABLE_STATIC_FALSE@ targets += ${pfx_solibs} ${pfb_solibs} ${pf4_solibs} ${pf6_solibs} ${pfa_solibs} ${pfx_symlink_files}
+-@ENABLE_STATIC_FALSE@ targets_install += ${pfx_solibs} ${pfb_solibs} ${pf4_solibs} ${pf6_solibs} ${pfa_solibs}
+-@ENABLE_STATIC_FALSE@ symlinks_install := ${pfx_symlink_files}
++libext_objs := ${pfx_objs}
++libext_ebt_objs := ${pfb_objs}
++libext_arpt_objs := ${pfa_objs}
++libext4_objs := ${pf4_objs}
++libext6_objs := ${pf6_objs}
++targets += ${pfx_solibs} ${pfb_solibs} ${pf4_solibs} ${pf6_solibs} ${pfa_solibs} ${pfx_symlink_files}
++targets_install := $(strip ${pfx_solibs} ${pfb_solibs} ${pf4_solibs} ${pf6_solibs} ${pfa_solibs})
++symlinks_install := ${pfx_symlink_files}
+ 
+ .SECONDARY:
+ 
+@@ -161,11 +181,11 @@ libext4.a: initext4.o ${libext4_objs}
+ libext6.a: initext6.o ${libext6_objs}
+ 	${AM_VERBOSE_AR} ${AR} crs $@ $^;
+ 
+-initext_func  := $(addprefix xt_,${pfx_build_mod})
+-initextb_func := $(addprefix ebt_,${pfb_build_mod})
+-initexta_func := $(addprefix arpt_,${pfa_build_mod})
+-initext4_func := $(addprefix ipt_,${pf4_build_mod})
+-initext6_func := $(addprefix ip6t_,${pf6_build_mod})
++initext_func  := $(addprefix xt_,${pfx_build_static})
++initextb_func := $(addprefix ebt_,${pfb_build_static})
++initexta_func := $(addprefix arpt_,${pfa_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/600-shared-libext.patch b/package/network/utils/iptables/patches/600-shared-libext.patch
new file mode 100644
index 0000000..819f628
--- /dev/null
+++ b/package/network/utils/iptables/patches/600-shared-libext.patch
@@ -0,0 +1,102 @@
+--- a/extensions/GNUmakefile.in
++++ b/extensions/GNUmakefile.in
+@@ -86,7 +86,7 @@ pfx_symlink_files := $(patsubst %,libxt_
+ #
+ # Building blocks
+ #
+-targets := libext.a libext4.a libext6.a libext_ebt.a libext_arpt.a matches.man targets.man
++targets := libiptext.so libiptext4.so libiptext6.so libiptext_ebt.so libiptext_arpt.so matches.man targets.man
+ targets_install :=
+ libext_objs := ${pfx_objs}
+ libext_ebt_objs := ${pfb_objs}
+@@ -132,7 +132,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
+ 
+@@ -164,22 +164,22 @@ xt_connlabel_LIBADD = @libnetfilter_conn
+ #	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 $(foreach obj,$^,${$(patsubst lib%.o,%,$(obj))_LIBADD});
+ 
+-libext_ebt.a: initextb.o ${libext_ebt_objs}
+-	${AM_VERBOSE_AR} ${AR} crs $@ $^;
++libiptext_ebt.so: initextb.o ${libext_ebt_objs}
++	${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $^ -L../libxtables/.libs -lxtables $(foreach obj,$^,${$(patsubst lib%.o,%,$(obj))_LIBADD});
+ 
+-libext_arpt.a: initexta.o ${libext_arpt_objs}
+-	${AM_VERBOSE_AR} ${AR} crs $@ $^;
++libiptext_arpt.so: initexta.o ${libext_arpt_objs}
++	${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $^ -L../libxtables/.libs -lxtables $(foreach obj,$^,${$(patsubst lib%.o,%,$(obj))_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 $(foreach obj,$^,${$(patsubst lib%.o,%,$(obj))_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 $(foreach obj,$^,${$(patsubst lib%.o,%,$(obj))_LIBADD});
+ 
+ initext_func  := $(addprefix xt_,${pfx_build_static})
+ initextb_func := $(addprefix ebt_,${pfb_build_static})
+--- a/iptables/Makefile.am
++++ b/iptables/Makefile.am
+@@ -7,19 +7,22 @@ BUILT_SOURCES =
+ 
+ xtables_legacy_multi_SOURCES  = xtables-legacy-multi.c iptables-xml.c
+ xtables_legacy_multi_CFLAGS   = ${AM_CFLAGS}
+-xtables_legacy_multi_LDADD    = ../extensions/libext.a
++xtables_legacy_multi_LDADD    =
++xtables_legacy_multi_LDFLAGS  = -L../extensions/ -liptext
+ if ENABLE_STATIC
+ xtables_legacy_multi_CFLAGS  += -DALL_INCLUSIVE
+ endif
+ if ENABLE_IPV4
+ xtables_legacy_multi_SOURCES += iptables-standalone.c iptables.c
+ xtables_legacy_multi_CFLAGS  += -DENABLE_IPV4
+-xtables_legacy_multi_LDADD   += ../libiptc/libip4tc.la ../extensions/libext4.a
++xtables_legacy_multi_LDADD   += ../libiptc/libip4tc.la
++xtables_legacy_multi_LDFLAGS += -liptext4
+ endif
+ if ENABLE_IPV6
+ xtables_legacy_multi_SOURCES += ip6tables-standalone.c ip6tables.c
+ xtables_legacy_multi_CFLAGS  += -DENABLE_IPV6
+-xtables_legacy_multi_LDADD   += ../libiptc/libip6tc.la ../extensions/libext6.a
++xtables_legacy_multi_LDADD   += ../libiptc/libip6tc.la
++xtables_legacy_multi_LDFLAGS += -liptext6
+ endif
+ xtables_legacy_multi_SOURCES += xshared.c iptables-restore.c iptables-save.c
+ xtables_legacy_multi_LDADD   += ../libxtables/libxtables.la -lm
+@@ -28,7 +31,8 @@ xtables_legacy_multi_LDADD   += ../libxt
+ if ENABLE_NFTABLES
+ xtables_nft_multi_SOURCES  = xtables-nft-multi.c iptables-xml.c
+ xtables_nft_multi_CFLAGS   = ${AM_CFLAGS}
+-xtables_nft_multi_LDADD    = ../extensions/libext.a ../extensions/libext_ebt.a
++xtables_nft_multi_LDADD    =
++xtables_nft_multi_LDFLAGS  = -L../extensions/ -liptext -liptext_ebt
+ if ENABLE_STATIC
+ xtables_nft_multi_CFLAGS  += -DALL_INCLUSIVE
+ endif
+@@ -42,7 +46,8 @@ xtables_nft_multi_SOURCES += xtables-sav
+ 				xtables-eb-standalone.c xtables-eb.c \
+ 				xtables-eb-translate.c \
+ 				xtables-translate.c
+-xtables_nft_multi_LDADD   += ${libmnl_LIBS} ${libnftnl_LIBS} ${libnetfilter_conntrack_LIBS} ../extensions/libext4.a ../extensions/libext6.a ../extensions/libext_ebt.a ../extensions/libext_arpt.a
++xtables_nft_multi_LDADD   += ${libmnl_LIBS} ${libnftnl_LIBS} ${libnetfilter_conntrack_LIBS}
++xtables_nft_multi_LDFLAGS += -liptext4 -liptext6 -liptext_arpt
+ xtables_nft_multi_SOURCES += xshared.c
+ xtables_nft_multi_LDADD   += ../libxtables/libxtables.la -lm
+ endif
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..cc451ef
--- /dev/null
+++ b/package/network/utils/iptables/patches/700-disable-legacy-revisions.patch
@@ -0,0 +1,95 @@
+--- a/extensions/libxt_conntrack.c
++++ b/extensions/libxt_conntrack.c
+@@ -1395,6 +1395,7 @@ static int conntrack3_mt6_xlate(struct x
+ }
+ 
+ static struct xtables_match conntrack_mt_reg[] = {
++#ifndef NO_LEGACY
+ 	{
+ 		.version       = XTABLES_VERSION,
+ 		.name          = "conntrack",
+@@ -1470,6 +1471,7 @@ static struct xtables_match conntrack_mt
+ 		.alias	       = conntrack_print_name_alias,
+ 		.x6_options    = conntrack2_mt_opts,
+ 	},
++#endif
+ 	{
+ 		.version       = XTABLES_VERSION,
+ 		.name          = "conntrack",
+@@ -1502,6 +1504,7 @@ static struct xtables_match conntrack_mt
+ 		.x6_options    = conntrack3_mt_opts,
+ 		.xlate	       = conntrack3_mt6_xlate,
+ 	},
++#ifndef NO_LEGACY
+ 	{
+ 		.family        = NFPROTO_UNSPEC,
+ 		.name          = "state",
+@@ -1532,6 +1535,8 @@ static struct xtables_match conntrack_mt
+ 		.x6_parse      = state_ct23_parse,
+ 		.x6_options    = state_opts,
+ 	},
++#endif
++#ifndef NO_LEGACY
+ 	{
+ 		.family        = NFPROTO_UNSPEC,
+ 		.name          = "state",
+@@ -1561,6 +1566,7 @@ static struct xtables_match conntrack_mt
+ 		.x6_parse      = state_parse,
+ 		.x6_options    = state_opts,
+ 	},
++#endif
+ };
+ 
+ void _init(void)
+--- a/extensions/libxt_CT.c
++++ b/extensions/libxt_CT.c
+@@ -363,6 +363,7 @@ static int xlate_ct1_tg(struct xt_xlate
+ }
+ 
+ static struct xtables_target ct_target_reg[] = {
++#ifndef NO_LEGACY
+ 	{
+ 		.family		= NFPROTO_UNSPEC,
+ 		.name		= "CT",
+@@ -388,6 +389,7 @@ static struct xtables_target ct_target_r
+ 		.x6_parse	= ct_parse_v1,
+ 		.x6_options	= ct_opts_v1,
+ 	},
++#endif
+ 	{
+ 		.family		= NFPROTO_UNSPEC,
+ 		.name		= "CT",
+@@ -403,6 +405,7 @@ static struct xtables_target ct_target_r
+ 		.x6_options	= ct_opts_v1,
+ 		.xlate		= xlate_ct1_tg,
+ 	},
++#ifndef NO_LEGACY
+ 	{
+ 		.family        = NFPROTO_UNSPEC,
+ 		.name          = "NOTRACK",
+@@ -441,6 +444,7 @@ static struct xtables_target ct_target_r
+ 		.revision      = 0,
+ 		.version       = XTABLES_VERSION,
+ 	},
++#endif
+ };
+ 
+ void _init(void)
+--- a/extensions/libxt_multiport.c
++++ b/extensions/libxt_multiport.c
+@@ -571,6 +571,7 @@ static int multiport_xlate6_v1(struct xt
+ }
+ 
+ static struct xtables_match multiport_mt_reg[] = {
++#ifndef NO_LEGACY
+ 	{
+ 		.family        = NFPROTO_IPV4,
+ 		.name          = "multiport",
+@@ -601,6 +602,7 @@ static struct xtables_match multiport_mt
+ 		.x6_options    = multiport_opts,
+ 		.xlate         = multiport_xlate6,
+ 	},
++#endif
+ 	{
+ 		.family        = NFPROTO_IPV4,
+ 		.name          = "multiport",
diff --git a/package/network/utils/iptables/patches/800-flowoffload_target.patch b/package/network/utils/iptables/patches/800-flowoffload_target.patch
new file mode 100644
index 0000000..2f79ee8
--- /dev/null
+++ b/package/network/utils/iptables/patches/800-flowoffload_target.patch
@@ -0,0 +1,95 @@
+--- /dev/null
++++ b/extensions/libxt_FLOWOFFLOAD.c
+@@ -0,0 +1,72 @@
++#include <stdio.h>
++#include <xtables.h>
++#include <linux/netfilter/xt_FLOWOFFLOAD.h>
++
++enum {
++    O_HW,
++};
++
++static void offload_help(void)
++{
++	printf(
++"FLOWOFFLOAD target options:\n"
++" --hw				Enable hardware offload\n"
++	);
++}
++
++static const struct xt_option_entry offload_opts[] = {
++	{.name = "hw", .id = O_HW, .type = XTTYPE_NONE},
++	XTOPT_TABLEEND,
++};
++
++static void offload_parse(struct xt_option_call *cb)
++{
++	struct xt_flowoffload_target_info *info = cb->data;
++
++	xtables_option_parse(cb);
++	switch (cb->entry->id) {
++	case O_HW:
++		info->flags |= XT_FLOWOFFLOAD_HW;
++		break;
++	}
++}
++
++static void offload_print(const void *ip, const struct xt_entry_target *target, int numeric)
++{
++	const struct xt_flowoffload_target_info *info =
++		(const struct xt_flowoffload_target_info *)target->data;
++
++	printf(" FLOWOFFLOAD");
++	if (info->flags & XT_FLOWOFFLOAD_HW)
++		printf(" hw");
++}
++
++static void offload_save(const void *ip, const struct xt_entry_target *target)
++{
++	const struct xt_flowoffload_target_info *info =
++		(const struct xt_flowoffload_target_info *)target->data;
++
++	if (info->flags & XT_FLOWOFFLOAD_HW)
++		printf(" --hw");
++}
++
++static struct xtables_target offload_tg_reg[] = {
++	{
++		.family		= NFPROTO_UNSPEC,
++		.name		= "FLOWOFFLOAD",
++		.revision	= 0,
++		.version	= XTABLES_VERSION,
++		.size		= XT_ALIGN(sizeof(struct xt_flowoffload_target_info)),
++		.userspacesize	= sizeof(struct xt_flowoffload_target_info),
++		.help		= offload_help,
++		.print		= offload_print,
++		.save		= offload_save,
++		.x6_parse	= offload_parse,
++		.x6_options	= offload_opts,
++	},
++};
++
++void _init(void)
++{
++	xtables_register_targets(offload_tg_reg, ARRAY_SIZE(offload_tg_reg));
++}
+--- /dev/null
++++ b/include/linux/netfilter/xt_FLOWOFFLOAD.h
+@@ -0,0 +1,17 @@
++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
++#ifndef _XT_FLOWOFFLOAD_H
++#define _XT_FLOWOFFLOAD_H
++
++#include <linux/types.h>
++
++enum {
++	XT_FLOWOFFLOAD_HW	= 1 << 0,
++
++	XT_FLOWOFFLOAD_MASK	= XT_FLOWOFFLOAD_HW
++};
++
++struct xt_flowoffload_target_info {
++	__u32 flags;
++};
++
++#endif /* _XT_FLOWOFFLOAD_H */
diff --git a/package/network/utils/iptables/patches/900-iptables-notify-fastpath.patch b/package/network/utils/iptables/patches/900-iptables-notify-fastpath.patch
new file mode 100644
index 0000000..d83102c
--- /dev/null
+++ b/package/network/utils/iptables/patches/900-iptables-notify-fastpath.patch
@@ -0,0 +1,239 @@
+--- a/libiptc/libiptc.c
++++ b/libiptc/libiptc.c
+@@ -2505,6 +2505,224 @@ static void counters_map_set(STRUCT_COUN
+ 	DEBUGP_C("SET\n");
+ }
+ 
++#define FASTPATH
++
++#ifdef FASTPATH
++#include <stdio.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <unistd.h>
++#include <poll.h>
++#include <string.h>
++#include <fcntl.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <sys/statfs.h>
++#include <sys/socket.h>
++#include <sys/types.h>
++#include <signal.h>
++#include <linux/magic.h>
++#include <linux/genetlink.h>
++
++/*
++ * Generic macros for dealing with netlink sockets. Might be duplicated
++ * elsewhere. It is recommended that commercial grade applications use
++ * libnl or libnetlink and use the interfaces provided by the library
++ */
++#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
++#define GENLMSG_PAYLOAD(glh) (NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN)
++#define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN))
++
++static bool proc_file_exists(const char *filename)
++{
++	struct stat s;
++	struct statfs f;
++
++	if (lstat(filename, &s))
++		return false;
++	if (!S_ISREG(s.st_mode))
++		return false;
++	if (statfs(filename, &f))
++		return false;
++	if (f.f_type != PROC_SUPER_MAGIC)
++		return false;
++	return true;
++}
++
++static int create_nl_socket(int protocol, int groups)
++{
++	socklen_t addr_len;
++	int fd;
++	struct sockaddr_nl local;
++
++	fd = socket(AF_NETLINK, SOCK_RAW, protocol);
++	if (fd < 0) {
++		perror("socket");
++		return -1;
++	}
++
++	memset(&local, 0, sizeof(local));
++	local.nl_family = AF_NETLINK;
++	local.nl_groups = groups;
++	if (bind(fd, (struct sockaddr *) &local, sizeof(local)) < 0)
++		goto error;
++
++	return fd;
++error:
++	close(fd);
++	return -1;
++}
++
++/*
++ * Send netlink message to kernel
++ */
++int sendto_fd(int s, const char *buf, int bufLen)
++{
++	struct sockaddr_nl nladdr;
++	int r;
++
++	memset(&nladdr, 0, sizeof(nladdr));
++	nladdr.nl_family = AF_NETLINK;
++
++	while ((r = sendto(s, buf, bufLen, 0, (struct sockaddr *) &nladdr,
++		sizeof(nladdr))) < bufLen) {
++		if (r > 0) {
++			buf += r;
++			bufLen -= r;
++		} else if (errno != EAGAIN) {
++			return -1;
++		}
++	}
++
++	return 0;
++}
++
++/*
++ * Probe the controller in genetlink to find the family id
++ * for the CONTROL_EXMPL family
++ */
++int get_family_id(int sd)
++{
++	struct {
++		struct nlmsghdr n;
++		struct genlmsghdr g;
++		char buf[256];
++	} family_req;
++
++	struct {
++		struct nlmsghdr n;
++		struct genlmsghdr g;
++		char buf[256];
++	} ans;
++
++	int id;
++	struct nlattr *na;
++	int rep_len;
++
++	/* Get family name */
++	family_req.n.nlmsg_type = GENL_ID_CTRL;
++	family_req.n.nlmsg_flags = NLM_F_REQUEST;
++	family_req.n.nlmsg_seq = 0;
++	family_req.n.nlmsg_pid = getpid();
++	family_req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
++	family_req.g.cmd = CTRL_CMD_GETFAMILY;
++	family_req.g.version = 0x1;
++
++	na = (struct nlattr *) GENLMSG_DATA(&family_req);
++	na->nla_type = CTRL_ATTR_FAMILY_NAME;
++
++	/*------change here--------*/
++	na->nla_len = strlen("FASTPATH") + 1 + NLA_HDRLEN;
++	strcpy(NLA_DATA(na), "FASTPATH");
++
++	family_req.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
++
++	if (sendto_fd(sd, (char *) &family_req, family_req.n.nlmsg_len) < 0)
++		return -1;
++
++	rep_len = recv(sd, &ans, sizeof(ans), 0);
++	if (rep_len < 0){
++		perror("recv");
++		return -1;
++	}
++
++	/* Validate response message */
++	if (!NLMSG_OK((&ans.n), rep_len)){
++		fprintf(stderr, "invalid reply message\n");
++		return -1;
++	}
++
++	if (ans.n.nlmsg_type == NLMSG_ERROR) { /* error */
++		fprintf(stderr, "received error\n");
++		return -1;
++	}
++
++	na = (struct nlattr *)GENLMSG_DATA(&ans);
++	na = (struct nlattr *)((char *) na + NLA_ALIGN(na->nla_len));
++	if (na->nla_type == CTRL_ATTR_FAMILY_ID) {
++		id = *(__u16 *)NLA_DATA(na);
++	}
++
++	return id;
++}
++
++static int tc_commit_notify_fastpath(void)
++{
++	struct {
++		struct nlmsghdr n;
++		struct genlmsghdr g;
++		char buf[256];
++	} ans;
++
++	struct {
++		struct nlmsghdr n;
++		struct genlmsghdr g;
++		char buf[256];
++	} req;
++
++	struct nlattr *na;
++	int nl_sd, id, mlength;
++	struct sockaddr_nl nladdr;
++	char *message = "TC_COMMIT!";
++
++	nl_sd = create_nl_socket(NETLINK_GENERIC,0);
++	if (nl_sd < 0) {
++		printf("create failure\n");
++		return -1;
++	}
++
++	id = get_family_id(nl_sd);
++	if (id < 0) {
++		printf("bad id\n");
++		return -1;
++	}
++
++	/* Send command needed */
++	req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
++	req.n.nlmsg_type = id;
++	req.n.nlmsg_flags = NLM_F_REQUEST;
++	req.n.nlmsg_seq = 60;
++	req.n.nlmsg_pid = getpid();
++	req.g.cmd = 1; //FASTPATH_NL_C_IPT_NOTIFY
++
++	/*compose message*/
++	na = (struct nlattr *)GENLMSG_DATA(&req);
++	na->nla_type = 1; //FASTPATH_NL_C_IPT_NOTIFY
++	mlength = strlen(message);
++	na->nla_len = mlength+NLA_HDRLEN; //message length
++	memcpy(NLA_DATA(na), message, mlength);
++	req.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
++
++	/*send message*/
++	memset(&nladdr, 0, sizeof(nladdr));
++	nladdr.nl_family = AF_NETLINK;
++
++	sendto(nl_sd, (char *)&req, req.n.nlmsg_len, 0,
++		(struct sockaddr *)&nladdr, sizeof(nladdr));
++	close(nl_sd);
++	return 0;
++}
++#endif
+ 
+ int
+ TC_COMMIT(struct xtc_handle *handle)
+@@ -2672,6 +2890,11 @@ TC_COMMIT(struct xtc_handle *handle)
+ 	free(repl);
+ 	free(newcounters);
+ 
++#ifdef FASTPATH
++	if (proc_file_exists("/proc/net/fastpath"))
++		tc_commit_notify_fastpath();
++#endif
++
+ finished:
+ 	return 1;
+ 
diff --git a/package/network/utils/iw/Makefile b/package/network/utils/iw/Makefile
new file mode 100644
index 0000000..1237c10
--- /dev/null
+++ b/package/network/utils/iw/Makefile
@@ -0,0 +1,75 @@
+#
+# 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:=6.9
+PKG_RELEASE:=1
+ 
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/software/network/iw
+PKG_HASH:=3f2db22ad41c675242b98ae3942dbf3112548c60a42ff739210f2de4e98e4894
+
+PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
+PKG_LICENSE:=GPL-2.0
+PKG_CPE_ID:=cpe:/a:kernel:iw
+
+PKG_BUILD_FLAGS:=gc-sections lto
+
+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
+  VARIANT:=tiny
+endef
+
+define Package/iw-full
+  $(Package/iw)
+  TITLE += (full version)
+  VARIANT:=full
+  PROVIDES:=iw
+endef
+
+define Build/Configure
+	echo "const char iw_version[] = \"$(PKG_VERSION)\";" > $(PKG_BUILD_DIR)/version.c
+	echo "#!/bin/sh" > $(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
+
+ifeq ($(BUILD_VARIANT),full)
+  TARGET_CPPFLAGS += -DIW_FULL
+  MAKE_FLAGS += IW_FULL=1
+endif
+
+MAKE_FLAGS += \
+	CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
+	LDFLAGS="$(TARGET_LDFLAGS)" \
+	NL1FOUND="" NL2FOUND=Y \
+	NLLIBNAME="libnl-tiny" \
+	LIBS="-lm -lnl-tiny" \
+	V=1
+
+define Package/iw/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/iw $(1)/usr/sbin/
+endef
+
+Package/iw-full/install=$(Package/iw/install)
+
+$(eval $(call BuildPackage,iw))
+$(eval $(call BuildPackage,iw-full))
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..f48c083
--- /dev/null
+++ b/package/network/utils/iw/patches/001-nl80211_h_sync.patch
@@ -0,0 +1,98 @@
+--- a/nl80211.h
++++ b/nl80211.h
+@@ -2061,6 +2061,10 @@ enum nl80211_commands {
+  * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported
+  *	interface combinations. In each nested item, it contains attributes
+  *	defined in &enum nl80211_if_combination_attrs.
++ *	If the wiphy uses multiple radios (@NL80211_ATTR_WIPHY_RADIOS is set),
++ *	this attribute contains the interface combinations of the first radio.
++ *	See @NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS for the global wiphy
++ *	combinations for the sum of all radios.
+  * @NL80211_ATTR_SOFTWARE_IFTYPES: Nested attribute (just like
+  *	%NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that
+  *	are managed in software: interfaces of these types aren't subject to
+@@ -2856,6 +2860,17 @@ enum nl80211_commands {
+  *	%NL80211_CMD_ASSOCIATE indicating the SPP A-MSDUs
+  *	are used on this connection
+  *
++ * @NL80211_ATTR_WIPHY_RADIOS: Nested attribute describing physical radios
++ *	belonging to this wiphy. See &enum nl80211_wiphy_radio_attrs.
++ *
++ * @NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS: Nested attribute listing the
++ *	supported interface combinations for all radios combined. In each
++ *	nested item, it contains attributes defined in
++ *	&enum nl80211_if_combination_attrs.
++ *
++ * @NL80211_ATTR_VIF_RADIO_MASK: Bitmask of allowed radios (u32).
++ *	A value of 0 means all radios.
++ *
+  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
+  * @NL80211_ATTR_MAX: highest attribute number currently defined
+  * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -3401,6 +3416,11 @@ enum nl80211_attrs {
+ 
+ 	NL80211_ATTR_ASSOC_SPP_AMSDU,
+ 
++	NL80211_ATTR_WIPHY_RADIOS,
++	NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS,
++
++	NL80211_ATTR_VIF_RADIO_MASK,
++
+ 	/* add attributes here, update the policy in nl80211.c */
+ 
+ 	__NL80211_ATTR_AFTER_LAST,
+@@ -7987,4 +8007,54 @@ enum nl80211_ap_settings_flags {
+ 	NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT	= 1 << 1,
+ };
+ 
++/**
++ * enum nl80211_wiphy_radio_attrs - wiphy radio attributes
++ *
++ * @__NL80211_WIPHY_RADIO_ATTR_INVALID: Invalid
++ *
++ * @NL80211_WIPHY_RADIO_ATTR_INDEX: Index of this radio (u32)
++ * @NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE: Frequency range supported by this
++ *	radio. Attribute may be present multiple times.
++ * @NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION: Supported interface
++ *	combination for this radio. Attribute may be present multiple times
++ *	and contains attributes defined in &enum nl80211_if_combination_attrs.
++ *
++ * @__NL80211_WIPHY_RADIO_ATTR_LAST: Internal
++ * @NL80211_WIPHY_RADIO_ATTR_MAX: Highest attribute
++ */
++enum nl80211_wiphy_radio_attrs {
++	__NL80211_WIPHY_RADIO_ATTR_INVALID,
++
++	NL80211_WIPHY_RADIO_ATTR_INDEX,
++	NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE,
++	NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION,
++
++	/* keep last */
++	__NL80211_WIPHY_RADIO_ATTR_LAST,
++	NL80211_WIPHY_RADIO_ATTR_MAX = __NL80211_WIPHY_RADIO_ATTR_LAST - 1,
++};
++
++/**
++ * enum nl80211_wiphy_radio_freq_range - wiphy radio frequency range
++ *
++ * @__NL80211_WIPHY_RADIO_FREQ_ATTR_INVALID: Invalid
++ *
++ * @NL80211_WIPHY_RADIO_FREQ_ATTR_START: Frequency range start (u32).
++ *	The unit is kHz.
++ * @NL80211_WIPHY_RADIO_FREQ_ATTR_END: Frequency range end (u32).
++ *	The unit is kHz.
++ *
++ * @__NL80211_WIPHY_RADIO_FREQ_ATTR_LAST: Internal
++ * @NL80211_WIPHY_RADIO_FREQ_ATTR_MAX: Highest attribute
++ */
++enum nl80211_wiphy_radio_freq_range {
++	__NL80211_WIPHY_RADIO_FREQ_ATTR_INVALID,
++
++	NL80211_WIPHY_RADIO_FREQ_ATTR_START,
++	NL80211_WIPHY_RADIO_FREQ_ATTR_END,
++
++	__NL80211_WIPHY_RADIO_FREQ_ATTR_LAST,
++	NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = __NL80211_WIPHY_RADIO_FREQ_ATTR_LAST - 1,
++};
++
+ #endif /* __LINUX_NL80211_H */
diff --git a/package/network/utils/iw/patches/010-Revert-iw-allow-specifying-CFLAGS-LIBS-externally.patch b/package/network/utils/iw/patches/010-Revert-iw-allow-specifying-CFLAGS-LIBS-externally.patch
new file mode 100644
index 0000000..1c93f00
--- /dev/null
+++ b/package/network/utils/iw/patches/010-Revert-iw-allow-specifying-CFLAGS-LIBS-externally.patch
@@ -0,0 +1,68 @@
+From 1f3706d10812d70adefe32fe0d7d3a3ec25374f0 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sun, 21 Nov 2021 00:02:57 +0100
+Subject: Revert "iw: allow specifying CFLAGS/LIBS externally"
+
+This reverts commit 1325244b77d56fd7a16d1e35fdae0efc151920b1.
+
+The OpenWrt build system provides the CFLAGS and LIBS names from the 
+package Makefile to overwrite them for libnl-tiny. This is not possible 
+after this upstream change which we revert here any more
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ Makefile | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+--- a/Makefile
++++ b/Makefile
+@@ -46,30 +46,30 @@ NLLIBNAME = libnl-1
+ endif
+ 
+ ifeq ($(NL2FOUND),Y)
+-override CFLAGS += -DCONFIG_LIBNL20
+-override LIBS += -lnl-genl
++CFLAGS += -DCONFIG_LIBNL20
++LIBS += -lnl-genl
+ NLLIBNAME = libnl-2.0
+ endif
+ 
+ ifeq ($(NL3xFOUND),Y)
+ # libnl 3.2 might be found as 3.2 and 3.0
+ NL3FOUND = N
+-override CFLAGS += -DCONFIG_LIBNL30
+-override LIBS += -lnl-genl-3
++CFLAGS += -DCONFIG_LIBNL30
++LIBS += -lnl-genl-3
+ NLLIBNAME = libnl-3.0
+ endif
+ 
+ ifeq ($(NL3FOUND),Y)
+-override CFLAGS += -DCONFIG_LIBNL30
+-override LIBS += -lnl-genl
++CFLAGS += -DCONFIG_LIBNL30
++LIBS += -lnl-genl
+ NLLIBNAME = libnl-3.0
+ endif
+ 
+ # nl-3.1 has a broken libnl-gnl-3.1.pc file
+ # as show by pkg-config --debug --libs --cflags --exact-version=3.1 libnl-genl-3.1;echo $?
+ ifeq ($(NL31FOUND),Y)
+-override CFLAGS += -DCONFIG_LIBNL30
+-override LIBS += -lnl-genl
++CFLAGS += -DCONFIG_LIBNL30
++LIBS += -lnl-genl
+ NLLIBNAME = libnl-3.1
+ endif
+ 
+@@ -77,8 +77,8 @@ ifeq ($(NLLIBNAME),)
+ $(error Cannot find development files for any supported version of libnl)
+ endif
+ 
+-override LIBS += $(shell $(PKG_CONFIG) --libs $(NLLIBNAME))
+-override CFLAGS += $(shell $(PKG_CONFIG) --cflags $(NLLIBNAME))
++LIBS += $(shell $(PKG_CONFIG) --libs $(NLLIBNAME))
++CFLAGS += $(shell $(PKG_CONFIG) --cflags $(NLLIBNAME))
+ endif # NO_PKG_CONFIG
+ 
+ ifeq ($(V),1)
diff --git a/package/network/utils/iw/patches/130-survey-bss-rx-time.patch b/package/network/utils/iw/patches/130-survey-bss-rx-time.patch
new file mode 100644
index 0000000..d488c14
--- /dev/null
+++ b/package/network/utils/iw/patches/130-survey-bss-rx-time.patch
@@ -0,0 +1,12 @@
+--- a/survey.c
++++ b/survey.c
+@@ -60,6 +60,9 @@ static int print_survey_handler(struct n
+ 	if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX])
+ 		printf("\tchannel receive time:\t\t%llu ms\n",
+ 			(unsigned long long)nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]));
++	if (sinfo[NL80211_SURVEY_INFO_TIME_BSS_RX])
++		printf("\tchannel BSS receive time:\t%llu ms\n",
++			(unsigned long long)nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BSS_RX]));
+ 	if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX])
+ 		printf("\tchannel transmit time:\t\t%llu ms\n",
+ 			(unsigned long long)nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]));
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..9924ffa
--- /dev/null
+++ b/package/network/utils/iw/patches/200-reduce_size.patch
@@ -0,0 +1,371 @@
+--- a/event.c
++++ b/event.c
+@@ -973,6 +973,7 @@ static int print_event(struct nl_msg *ms
+ 	}
+ 
+ 	switch (gnlh->cmd) {
++#ifdef IW_FULL
+ 	case NL80211_CMD_NEW_WIPHY:
+ 		printf("renamed to %s\n", nla_get_string(tb[NL80211_ATTR_WIPHY_NAME]));
+ 		break;
+@@ -1008,6 +1009,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_WIPHY_REG_CHANGE:
+ 	case NL80211_CMD_REG_CHANGE:
+ 		if (gnlh->cmd == NL80211_CMD_WIPHY_REG_CHANGE)
+@@ -1090,6 +1092,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;
++#ifdef IW_FULL
+ 	case NL80211_CMD_JOIN_IBSS:
+ 		mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
+ 		printf("IBSS %s joined\n", macbuf);
+@@ -1297,9 +1300,9 @@ static int print_event(struct nl_msg *ms
+ 	case NL80211_CMD_ASSOC_COMEBACK: /* 147 */
+ 		parse_assoc_comeback(tb, gnlh->cmd);
+ 		break;
++#endif
+ 	default:
+-		printf("unknown event %d (%s)\n",
+-		       gnlh->cmd, command_name(gnlh->cmd));
++		printf("unknown event %d\n", gnlh->cmd);
+ 		break;
+ 	}
+ 
+--- a/info.c
++++ b/info.c
+@@ -446,6 +446,7 @@ next:
+ 				}
+ 			}
+ 
++#ifdef IW_FULL
+ 			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) {
+@@ -462,6 +463,7 @@ next:
+ 				printf("\n");
+ 			}
+ 			}
++#endif
+ 		}
+ 	}
+ 
+@@ -527,6 +529,7 @@ next:
+ 		printf("\tCoverage class: %d (up to %dm)\n", coverage, 450 * coverage);
+ 	}
+ 
++#ifdef IW_FULL
+ 	if (tb_msg[NL80211_ATTR_CIPHER_SUITES]) {
+ 		int num = nla_len(tb_msg[NL80211_ATTR_CIPHER_SUITES]) / sizeof(__u32);
+ 		int i;
+@@ -538,6 +541,7 @@ next:
+ 					cipher_name(ciphers[i]));
+ 		}
+ 	}
++#endif
+ 
+ 	if (tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX] &&
+ 	    tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX])
+@@ -555,9 +559,11 @@ next:
+ 		print_iftype_list("\tSupported interface modes", "\t\t",
+ 				  tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES]);
+ 
++#ifdef IW_FULL
+ 	if (tb_msg[NL80211_ATTR_SOFTWARE_IFTYPES])
+ 		print_iftype_list("\tsoftware interface modes (can always be added)",
+ 				  "\t\t", tb_msg[NL80211_ATTR_SOFTWARE_IFTYPES]);
++#endif
+ 
+ 	if (tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS]) {
+ 		struct nlattr *nl_combi;
+@@ -647,6 +653,7 @@ broken_combination:
+ 			printf("\tinterface combinations are not supported\n");
+ 	}
+ 
++#ifdef IW_FULL
+ 	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)
+@@ -744,6 +751,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");
+@@ -782,6 +790,7 @@ broken_combination:
+ 		}
+ 	}
+ 
++#ifdef IW_FULL
+ 	if (tb_msg[NL80211_ATTR_FEATURE_FLAGS]) {
+ 		unsigned int features = nla_get_u32(tb_msg[NL80211_ATTR_FEATURE_FLAGS]);
+ 
+@@ -846,6 +855,7 @@ broken_combination:
+ 		if (features & NL80211_FEATURE_ND_RANDOM_MAC_ADDR)
+ 			printf("\tDevice supports randomizing MAC-addr in net-detect scans.\n");
+ 	}
++#endif
+ 
+ 	if (tb_msg[NL80211_ATTR_TDLS_SUPPORT])
+ 		printf("\tDevice supports T-DLS.\n");
+@@ -914,6 +924,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);
+ 
++#ifdef IW_FULL
+ static int handle_commands(struct nl80211_state *state, struct nl_msg *msg,
+ 			   int argc, char **argv, enum id_input id)
+ {
+@@ -925,6 +936,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
+@@ -1308,6 +1308,9 @@ 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]);
++#ifndef IW_FULL
++	return;
++#endif
+ 	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);
+@@ -1818,30 +1821,31 @@ 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) | BIT(PRINT_LINK_MLO_MLD), },
++	[11] = { "BSS Load", print_bss_load, 5, 5, BIT(PRINT_SCAN), },
++	[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), },
++	[114] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), },
++	[191] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), },
++	[192] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), },
++#ifdef IW_FULL
+ 	[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), },
+ 	[6] = { "IBSS ATIM window", print_ibssatim, 2, 2, BIT(PRINT_SCAN), },
+ 	[7] = { "Country", print_country, 3, 255, BIT(PRINT_SCAN), },
+-	[11] = { "BSS Load", print_bss_load, 5, 5, BIT(PRINT_SCAN), },
+ 	[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), },
+ 	[51] = { "AP Channel Report", print_ap_channel_report, 1, 255, BIT(PRINT_SCAN), },
+ 	[59] = { "Supported operating classes", print_supp_op_classes, 1, 255, BIT(PRINT_SCAN), },
+ 	[66] = { "Measurement Pilot Transmission", print_measurement_pilot_tx, 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), },
+ 	[70] = { "RM enabled capabilities", print_rm_enabled_capabilities, 5, 5, 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), },
+ 	[127] = { "Extended capabilities", print_capabilities, 0, 255, BIT(PRINT_SCAN), },
+ 	[107] = { "802.11u Interworking", print_interworking, 0, 255, BIT(PRINT_SCAN), },
+ 	[108] = { "802.11u Advertisement", print_11u_advert, 0, 255, BIT(PRINT_SCAN), },
+@@ -1850,6 +1854,7 @@ static const struct ie_print ieprinters[
+ 	[214] = { "Short beacon interval", print_short_beacon_int, 2, 2, BIT(PRINT_SCAN), },
+ 	[217] = { "S1G capabilities", print_s1g_capa, 15, 15, BIT(PRINT_SCAN), },
+ 	[232] = { "S1G operation", print_s1g_oper, 6, 6, BIT(PRINT_SCAN), },
++#endif
+ };
+ 
+ static void print_wifi_wpa(const uint8_t type, uint8_t len, const uint8_t *data,
+@@ -2185,8 +2190,10 @@ static void print_wifi_wps(const uint8_t
+ 
+ static const struct ie_print wifiprinters[] = {
+ 	[1] = { "WPA", print_wifi_wpa, 2, 255, BIT(PRINT_SCAN), },
++#ifdef IW_FULL
+ 	[2] = { "WMM", print_wifi_wmm, 1, 255, BIT(PRINT_SCAN), },
+ 	[4] = { "WPS", print_wifi_wps, 0, 255, BIT(PRINT_SCAN), },
++#endif
+ };
+ 
+ static inline void print_p2p(const uint8_t type, uint8_t len,
+@@ -2349,6 +2356,10 @@ static void print_vendor(unsigned char l
+ 		return;
+ 	}
+ 
++#ifdef IW_FULL
++	return;
++#endif
++
+ 	if (len >= 4 && memcmp(data, wfa_oui, 3) == 0) {
+ 		if (data[3] < ARRAY_SIZE(wfa_printers) &&
+ 		    wfa_printers[data[3]].name &&
+@@ -2483,6 +2494,7 @@ static void print_capa_non_dmg(__u16 cap
+ 		printf(" ESS");
+ 	if (capa & WLAN_CAPABILITY_IBSS)
+ 		printf(" IBSS");
++#ifdef IW_FULL
+ 	if (capa & WLAN_CAPABILITY_CF_POLLABLE)
+ 		printf(" CfPollable");
+ 	if (capa & WLAN_CAPABILITY_CF_POLL_REQUEST)
+@@ -2511,6 +2523,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)
+@@ -2601,8 +2614,10 @@ static int print_bss_handler(struct nl_m
+ 		else
+ 			printf("\tfreq: %d\n", freq);
+ 
++#ifdef IW_FULL
+ 		if (freq > 45000)
+ 			is_dmg = true;
++#endif
+ 	}
+ 	if (bss[NL80211_BSS_BEACON_INTERVAL])
+ 		printf("\tbeacon interval: %d TUs\n",
+@@ -2796,6 +2811,7 @@ static int handle_stop_sched_scan(struct
+ 	return 0;
+ }
+ 
++#ifdef IW_FULL
+ COMMAND(scan, sched_start,
+ 	SCHED_SCAN_OPTIONS,
+ 	NL80211_CMD_START_SCHED_SCAN, 0, CIB_NETDEV, handle_start_sched_scan,
+@@ -2806,3 +2822,4 @@ COMMAND(scan, sched_start,
+ COMMAND(scan, sched_stop, "",
+ 	NL80211_CMD_STOP_SCHED_SCAN, 0, CIB_NETDEV, handle_stop_sched_scan,
+ 	"Stop an ongoing scheduled scan.");
++#endif
+--- a/util.c
++++ b/util.c
+@@ -153,6 +153,7 @@ static const char *commands[NL80211_CMD_
+ 
+ static char cmdbuf[100];
+ 
++#ifdef IW_FULL
+ const char *command_name(enum nl80211_commands cmd)
+ {
+ 	if (cmd <= NL80211_CMD_MAX && commands[cmd])
+@@ -160,6 +161,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)
+ {
+@@ -313,6 +315,9 @@ int parse_keys(struct nl_msg *msg, char
+ 	char keybuf[13];
+ 	int pos = 0;
+ 
++#ifndef IW_FULL
++	return 1;
++#endif
+ 	if (!*argc)
+ 		return 1;
+ 
+--- a/Makefile
++++ b/Makefile
+@@ -24,6 +24,12 @@ _OBJS := $(sort $(patsubst %.c,%.o,$(wil
+ VERSION_OBJS := $(filter-out version.o, $(_OBJS))
+ OBJS := $(VERSION_OBJS) version.o
+ 
++OBJS_FULL = ocb offch cqm wowlan coalesce roc p2p vendor mgmt ap sha256 nan bloom measurements ftm
++ifdef IW_FULL
++  CFLAGS += -DIW_FULL
++else
++  OBJS:=$(filter-out $(patsubst %,%.o,$(OBJS_FULL)),$(OBJS))
++endif
+ ALL = iw
+ 
+ ifeq ($(NO_PKG_CONFIG),)
+--- a/station.c
++++ b/station.c
+@@ -801,10 +801,12 @@ static int handle_station_set_plink(stru
+  nla_put_failure:
+ 	return -ENOBUFS;
+ }
++#ifdef IW_FULL
+ COMMAND_ALIAS(station, set, "<MAC address> plink_action <open|block>",
+ 	NL80211_CMD_SET_STATION, 0, CIB_NETDEV, handle_station_set_plink,
+ 	"Set mesh peer link action for this station (peer).",
+ 	select_station_cmd, station_set_plink);
++#endif
+ 
+ static int handle_station_set_vlan(struct nl80211_state *state,
+ 				   struct nl_msg *msg,
+@@ -899,11 +901,13 @@ static int handle_station_set_mesh_power
+ nla_put_failure:
+ 	return -ENOBUFS;
+ }
++#ifdef IW_FULL
+ COMMAND_ALIAS(station, set, "<MAC address> mesh_power_mode "
+ 	"<active|light|deep>", NL80211_CMD_SET_STATION, 0, CIB_NETDEV,
+ 	handle_station_set_mesh_power_mode,
+ 	"Set link-specific mesh power mode for this station",
+ 	select_station_cmd, station_set_mesh_power_mode);
++#endif
+ 
+ static int handle_station_set_airtime_weight(struct nl80211_state *state,
+ 					     struct nl_msg *msg,
+--- a/interface.c
++++ b/interface.c
+@@ -668,9 +668,11 @@ static int handle_interface_wds_peer(str
+  nla_put_failure:
+ 	return -ENOBUFS;
+ }
++#ifdef IW_FULL
+ COMMAND(set, peer, "<MAC address>",
+ 	NL80211_CMD_SET_WDS_PEER, 0, CIB_NETDEV, handle_interface_wds_peer,
+ 	"Set interface WDS peer.");
++#endif
+ 
+ static int set_mcast_rate(struct nl80211_state *state,
+ 			  struct nl_msg *msg,
+@@ -760,6 +762,7 @@ static int handle_chan(struct nl80211_st
+ 	return handle_chanfreq(state, msg, true, argc, argv, id);
+ }
+ 
++#ifdef IW_FULL
+ SECTION(switch);
+ COMMAND(switch, freq,
+ 	"<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz] [beacons <count>] [block-tx]\n"
+@@ -1031,3 +1034,4 @@ COMMAND(set, tidconf, "[peer <MAC addres
+ 	"  $ iw dev wlan0 set tidconf peer xx:xx:xx:xx:xx:xx tids 0x2 bitrates auto\n"
+ 	"  $ iw dev wlan0 set tidconf peer xx:xx:xx:xx:xx:xx tids 0x2 bitrates limit vht-mcs-5 4:9\n"
+ 	);
++#endif
+--- a/phy.c
++++ b/phy.c
+@@ -403,6 +403,7 @@ err_out:
+ 		free(cac_trigger_argv);
+ 	return err;
+ }
++#ifdef IW_FULL
+ TOPLEVEL(cac, "channel <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
+ 	      "freq <freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
+ 	      "freq <control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
+@@ -422,6 +423,7 @@ COMMAND(cac, background,
+ 	NL80211_CMD_RADAR_DETECT, 0, CIB_NETDEV, handle_cac_background,
+ 	"Start background channel availability check (CAC) looking to look for\n"
+ 	"radars on the given channel.");
++#endif
+ 
+ static int handle_fragmentation(struct nl80211_state *state,
+ 				struct nl_msg *msg,
diff --git a/package/network/utils/iw/patches/300-wiphy_radios.patch b/package/network/utils/iw/patches/300-wiphy_radios.patch
new file mode 100644
index 0000000..534addf
--- /dev/null
+++ b/package/network/utils/iw/patches/300-wiphy_radios.patch
@@ -0,0 +1,252 @@
+--- a/info.c
++++ b/info.c
+@@ -295,6 +295,151 @@ static void print_pmsr_capabilities(stru
+ 	}
+ }
+ 
++static void print_interface_combinations(struct nlattr *ifcomb, bool radio)
++{
++	const char *indent = radio ? "\t" : "";
++	struct nlattr *nl_combi;
++	bool have_combinations = false;
++	int rem;
++
++	nla_for_each_nested(nl_combi, ifcomb, rem) {
++		static struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
++			[NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
++			[NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
++			[NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
++			[NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
++			[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 },
++		};
++		struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
++		static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
++			[NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
++			[NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
++		};
++		struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
++		struct nlattr *nl_limit;
++		int err, rem_limit;
++		bool comma = false;
++
++		if (radio && nla_type(nl_combi) !=
++			     NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION)
++			continue;
++
++		if (!have_combinations) {
++			printf("\t%svalid interface combinations:\n", indent);
++			have_combinations = true;
++		}
++
++		printf("\t\t%s * ", indent);
++
++		err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
++					   nl_combi, iface_combination_policy);
++		if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
++			!tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
++			!tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]) {
++			printf(" <failed to parse>\n");
++			goto broken_combination;
++		}
++
++		nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS], rem_limit) {
++			err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT,
++						   nl_limit, iface_limit_policy);
++			if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES]) {
++				printf("<failed to parse>\n");
++				goto broken_combination;
++			}
++
++			if (comma)
++				printf(", ");
++			comma = true;
++			printf("#{ ");
++			print_iftype_line(tb_limit[NL80211_IFACE_LIMIT_TYPES]);
++			printf(" } <= %u", nla_get_u32(tb_limit[NL80211_IFACE_LIMIT_MAX]));
++		}
++		printf(",\n\t\t%s   ", indent);
++
++		printf("total <= %d, #channels <= %d%s",
++			nla_get_u32(tb_comb[NL80211_IFACE_COMB_MAXNUM]),
++			nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]),
++			tb_comb[NL80211_IFACE_COMB_STA_AP_BI_MATCH] ?
++				", STA/AP BI must match" : "");
++		if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]) {
++			unsigned long widths = nla_get_u32(tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]);
++
++			if (widths) {
++				int width;
++				bool first = true;
++
++				printf(", radar detect widths: {");
++				for (width = 0; width < 32; width++)
++					if (widths & (1 << width)) {
++						printf("%s %s",
++							   first ? "":",",
++							   channel_width_name(width));
++						first = false;
++					}
++				printf(" }\n");
++			}
++		}
++		printf("\n");
++broken_combination:
++		;
++	}
++
++	if (!have_combinations)
++		printf("\t%sinterface combinations are not supported\n", indent);
++}
++
++static void print_radio_freq(struct nlattr *freqs)
++{
++	struct nlattr *freq;
++	int rem;
++
++	nla_for_each_nested(freq, freqs, rem) {
++		static struct nla_policy freq_policy[NL80211_WIPHY_RADIO_FREQ_ATTR_MAX + 1] = {
++			[NL80211_WIPHY_RADIO_FREQ_ATTR_START] = { .type = NLA_U32 },
++			[NL80211_WIPHY_RADIO_FREQ_ATTR_END] = { .type = NLA_U32 },
++		};
++		struct nlattr *tb[NL80211_WIPHY_RADIO_FREQ_ATTR_MAX + 1];
++		uint32_t start, end;
++
++		if (nla_type(freq) != NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE)
++			continue;
++
++		if (nla_parse_nested(tb, NL80211_WIPHY_RADIO_ATTR_MAX + 1,
++				     freq, freq_policy) ||
++		    !tb[NL80211_WIPHY_RADIO_FREQ_ATTR_START] ||
++		    !tb[NL80211_WIPHY_RADIO_FREQ_ATTR_END])
++			continue;
++
++		start = nla_get_u32(tb[NL80211_WIPHY_RADIO_FREQ_ATTR_START]);
++		end = nla_get_u32(tb[NL80211_WIPHY_RADIO_FREQ_ATTR_END]);
++
++		printf("\t\tfreq range: %.1f MHz - %.1f MHz\n", (float)start / 1000, (float)end / 1000);
++	}
++}
++
++static void print_radios(struct nlattr *radios)
++{
++	struct nlattr *radio;
++	int rem, idx = 0;
++
++	nla_for_each_nested(radio, radios, rem) {
++		static struct nla_policy radio_policy[NL80211_WIPHY_RADIO_ATTR_MAX + 1] = {
++			[NL80211_WIPHY_RADIO_ATTR_INDEX] = { .type = NLA_U32 },
++		};
++		struct nlattr *tb[NL80211_WIPHY_RADIO_ATTR_MAX + 1];
++
++		if (nla_parse_nested(tb, NL80211_WIPHY_RADIO_ATTR_MAX + 1,
++				     radio, radio_policy) ||
++		    !tb[NL80211_WIPHY_RADIO_ATTR_INDEX])
++			continue;
++
++		printf("\twiphy radio %d:\n", nla_get_u32(tb[NL80211_WIPHY_RADIO_ATTR_INDEX]));
++		print_radio_freq(radio);
++		print_interface_combinations(radio, true);
++	}
++}
++
+ static int print_phy_handler(struct nl_msg *msg, void *arg)
+ {
+ 	struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
+@@ -565,93 +710,11 @@ next:
+ 				  "\t\t", tb_msg[NL80211_ATTR_SOFTWARE_IFTYPES]);
+ #endif
+ 
+-	if (tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS]) {
+-		struct nlattr *nl_combi;
+-		int rem_combi;
+-		bool have_combinations = false;
+-
+-		nla_for_each_nested(nl_combi, tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS], rem_combi) {
+-			static struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
+-				[NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
+-				[NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
+-				[NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
+-				[NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
+-				[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 },
+-			};
+-			struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
+-			static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
+-				[NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
+-				[NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
+-			};
+-			struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
+-			struct nlattr *nl_limit;
+-			int err, rem_limit;
+-			bool comma = false;
+-
+-			if (!have_combinations) {
+-				printf("\tvalid interface combinations:\n");
+-				have_combinations = true;
+-			}
+-
+-			printf("\t\t * ");
++	if (tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS])
++		print_interface_combinations(tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS], false);
+ 
+-			err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
+-					       nl_combi, iface_combination_policy);
+-			if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
+-			    !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
+-			    !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]) {
+-				printf(" <failed to parse>\n");
+-				goto broken_combination;
+-			}
+-
+-			nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS], rem_limit) {
+-				err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT,
+-						       nl_limit, iface_limit_policy);
+-				if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES]) {
+-					printf("<failed to parse>\n");
+-					goto broken_combination;
+-				}
+-
+-				if (comma)
+-					printf(", ");
+-				comma = true;
+-				printf("#{ ");
+-				print_iftype_line(tb_limit[NL80211_IFACE_LIMIT_TYPES]);
+-				printf(" } <= %u", nla_get_u32(tb_limit[NL80211_IFACE_LIMIT_MAX]));
+-			}
+-			printf(",\n\t\t   ");
+-
+-			printf("total <= %d, #channels <= %d%s",
+-				nla_get_u32(tb_comb[NL80211_IFACE_COMB_MAXNUM]),
+-				nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]),
+-				tb_comb[NL80211_IFACE_COMB_STA_AP_BI_MATCH] ?
+-					", STA/AP BI must match" : "");
+-			if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]) {
+-				unsigned long widths = nla_get_u32(tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]);
+-
+-				if (widths) {
+-					int width;
+-					bool first = true;
+-
+-					printf(", radar detect widths: {");
+-					for (width = 0; width < 32; width++)
+-						if (widths & (1 << width)) {
+-							printf("%s %s",
+-							       first ? "":",",
+-							       channel_width_name(width));
+-							first = false;
+-						}
+-					printf(" }\n");
+-				}
+-			}
+-			printf("\n");
+-broken_combination:
+-			;
+-		}
+-
+-		if (!have_combinations)
+-			printf("\tinterface combinations are not supported\n");
+-	}
++	if (tb_msg[NL80211_ATTR_WIPHY_RADIOS])
++		print_radios(tb_msg[NL80211_ATTR_WIPHY_RADIOS]);
+ 
+ #ifdef IW_FULL
+ 	if (tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS]) {
diff --git a/package/network/utils/iw/patches/310-vif_radio_mask.patch b/package/network/utils/iw/patches/310-vif_radio_mask.patch
new file mode 100644
index 0000000..724f71c
--- /dev/null
+++ b/package/network/utils/iw/patches/310-vif_radio_mask.patch
@@ -0,0 +1,99 @@
+--- a/interface.c
++++ b/interface.c
+@@ -226,6 +226,43 @@ nla_put_failure:
+ 	return 1;
+ }
+ 
++static int parse_radio_list(char *str, struct nl_msg *msg)
++{
++	unsigned int mask = 0;
++	unsigned long id;
++	char *end;
++
++	if (!str)
++		return 1;
++
++	if (!strcmp(str, "all"))
++		goto out;
++
++	while (1) {
++		if (!*str)
++			return 1;
++
++		id = strtoul(str, &end, 0);
++		if (id > 31)
++			return 1;
++
++		mask |= 1 << id;
++		if (!*end)
++			break;
++
++		if (end == str || *end != ',')
++			return 1;
++
++		str = end + 1;
++	}
++
++out:
++	NLA_PUT_U32(msg, NL80211_ATTR_VIF_RADIO_MASK, mask);
++	return 0;
++nla_put_failure:
++	return 1;
++}
++
+ static int handle_interface_add(struct nl80211_state *state,
+ 				struct nl_msg *msg,
+ 				int argc, char **argv,
+@@ -287,6 +324,15 @@ try_another:
+ 				fprintf(stderr, "flags error\n");
+ 				return 2;
+ 			}
++		} else if (strcmp(argv[0], "radios") == 0) {
++			argc--;
++			argv++;
++			if (parse_radio_list(argv[0], msg)) {
++				fprintf(stderr, "Invalid radio list\n");
++				return 2;
++			}
++			argc--;
++			argv++;
+ 		} else {
+ 			return 1;
+ 		}
+@@ -306,14 +352,14 @@ try_another:
+  nla_put_failure:
+ 	return -ENOBUFS;
+ }
+-COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [4addr on|off] [flags <flag>*] [addr <mac-addr>]",
++COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [4addr on|off] [flags <flag>*] [addr <mac-addr>] [radios all|<id>[,<id>...]]",
+ 	NL80211_CMD_NEW_INTERFACE, 0, CIB_PHY, handle_interface_add,
+ 	"Add a new virtual interface with the given configuration.\n"
+ 	IFACE_TYPES "\n\n"
+ 	"The flags are only used for monitor interfaces, valid flags are:\n"
+ 	VALID_FLAGS "\n\n"
+ 	"The mesh_id is used only for mesh mode.");
+-COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [4addr on|off] [flags <flag>*] [addr <mac-addr>]",
++COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [4addr on|off] [flags <flag>*] [addr <mac-addr>] [radios all|<id>[,<id>...]]",
+ 	NL80211_CMD_NEW_INTERFACE, 0, CIB_NETDEV, handle_interface_add, NULL);
+ 
+ static int handle_interface_del(struct nl80211_state *state,
+@@ -493,6 +539,19 @@ static int print_iface_handler(struct nl
+ 			printf("\n");
+ 		}
+ 	}
++
++	if (tb_msg[NL80211_ATTR_VIF_RADIO_MASK]) {
++		uint32_t mask = nla_get_u32(tb_msg[NL80211_ATTR_VIF_RADIO_MASK]);
++		int i;
++
++		if (mask) {
++			printf("%s\tRadios:", indent);
++			for (i = 0; mask; i++, mask >>= 1)
++				if (mask & 1)
++					printf(" %d", i);
++			printf("\n");
++		}
++	}
+ 
+ 	return NL_SKIP;
+ }
diff --git a/package/network/utils/iwcap/Makefile b/package/network/utils/iwcap/Makefile
new file mode 100644
index 0000000..7b43d62
--- /dev/null
+++ b/package/network/utils/iwcap/Makefile
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2012 Jo-Philipp Wich <jo@mein.io>
+#
+# 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 <jo@mein.io>
+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/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..bc69550
--- /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 <jo@mein.io>
+ *
+ *    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_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;
+		}
+		if (run_stop)
+		{
+			msg("Shutting down ...\n");
+
+			if (promisc)
+				set_promisc(0);
+
+			if (ring)
+				ringbuf_free(ring);
+
+			return 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..9055fa2
--- /dev/null
+++ b/package/network/utils/iwinfo/Makefile
@@ -0,0 +1,121 @@
+#
+# Copyright (C) 2010-2016 Jo-Philipp Wich <jo@mein.io>
+#
+# This is free software, licensed under the GPL 2 license.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libiwinfo
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL=$(PROJECT_GIT)/project/iwinfo.git
+PKG_SOURCE_DATE:=2024-10-20
+PKG_SOURCE_VERSION:=b94f066e3f5839b8509483cdd8f4f582a45fa233
+PKG_MIRROR_HASH:=a29bd61d17e4f2d21a3c89fdd6a9776dbefad1396ede7cd0a8813506e35f73b8
+PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
+PKG_LICENSE:=GPL-2.0
+
+PKG_BUILD_FLAGS:=no-lto
+
+IWINFO_ABI_VERSION:=20230701
+
+include $(INCLUDE_DIR)/package.mk
+
+
+define Package/libiwinfo
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE:=Generalized Wireless Information Library (iwinfo)
+  DEPENDS:=+libnl-tiny +libuci +libubus +libiwinfo-data
+  ABI_VERSION:=$(IWINFO_ABI_VERSION)
+endef
+
+define Package/libiwinfo/description
+  Wireless information library with simplified API for 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/libiwinfo-data
+  TITLE:=libiwinfo Lua binding
+  HIDDEN:=1
+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
+
+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="nl80211" \
+	SOVERSION="$(IWINFO_ABI_VERSION)"
+
+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
+	$(CP) $(PKG_BUILD_DIR)/libiwinfo.so* $(1)/usr/lib/
+	$(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.$(IWINFO_ABI_VERSION) $(1)/usr/lib/libiwinfo.so.$(IWINFO_ABI_VERSION)
+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/libiwinfo-data/install
+	$(INSTALL_DIR) $(1)/usr/share/libiwinfo
+	$(INSTALL_DATA) $(PKG_BUILD_DIR)/devices.txt $(1)/usr/share/libiwinfo/devices.txt
+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,libiwinfo-data))
+$(eval $(call BuildPackage,iwinfo))
diff --git a/package/network/utils/iwinfo/patches/100-multi_radio.patch b/package/network/utils/iwinfo/patches/100-multi_radio.patch
new file mode 100644
index 0000000..3ad3b4f
--- /dev/null
+++ b/package/network/utils/iwinfo/patches/100-multi_radio.patch
@@ -0,0 +1,1498 @@
+--- a/api/nl80211.h
++++ b/api/nl80211.h
+@@ -11,7 +11,7 @@
+  * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
+  * Copyright 2008 Colin McCabe <colin@cozybit.com>
+  * Copyright 2015-2017	Intel Deutschland GmbH
+- * Copyright (C) 2018-2023 Intel Corporation
++ * Copyright (C) 2018-2024 Intel Corporation
+  *
+  * Permission to use, copy, modify, and/or distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+@@ -72,7 +72,7 @@
+  * For drivers supporting TDLS with external setup (WIPHY_FLAG_SUPPORTS_TDLS
+  * and WIPHY_FLAG_TDLS_EXTERNAL_SETUP), the station lifetime is as follows:
+  *  - a setup station entry is added, not yet authorized, without any rate
+- *    or capability information, this just exists to avoid race conditions
++ *    or capability information; this just exists to avoid race conditions
+  *  - when the TDLS setup is done, a single NL80211_CMD_SET_STATION is valid
+  *    to add rate and capability information to the station and at the same
+  *    time mark it authorized.
+@@ -87,7 +87,7 @@
+  * DOC: Frame transmission/registration support
+  *
+  * Frame transmission and registration support exists to allow userspace
+- * management entities such as wpa_supplicant react to management frames
++ * management entities such as wpa_supplicant to react to management frames
+  * that are not being handled by the kernel. This includes, for example,
+  * certain classes of action frames that cannot be handled in the kernel
+  * for various reasons.
+@@ -113,7 +113,7 @@
+  *
+  * Frame transmission allows userspace to send for example the required
+  * responses to action frames. It is subject to some sanity checking,
+- * but many frames can be transmitted. When a frame was transmitted, its
++ * but many frames can be transmitted. When a frame is transmitted, its
+  * status is indicated to the sending socket.
+  *
+  * For more technical details, see the corresponding command descriptions
+@@ -123,7 +123,7 @@
+ /**
+  * DOC: Virtual interface / concurrency capabilities
+  *
+- * Some devices are able to operate with virtual MACs, they can have
++ * Some devices are able to operate with virtual MACs; they can have
+  * more than one virtual interface. The capability handling for this
+  * is a bit complex though, as there may be a number of restrictions
+  * on the types of concurrency that are supported.
+@@ -135,7 +135,7 @@
+  * Once concurrency is desired, more attributes must be observed:
+  * To start with, since some interface types are purely managed in
+  * software, like the AP-VLAN type in mac80211 for example, there's
+- * an additional list of these, they can be added at any time and
++ * an additional list of these; they can be added at any time and
+  * are only restricted by some semantic restrictions (e.g. AP-VLAN
+  * cannot be added without a corresponding AP interface). This list
+  * is exported in the %NL80211_ATTR_SOFTWARE_IFTYPES attribute.
+@@ -164,17 +164,17 @@
+  * Packet coalesce feature helps to reduce number of received interrupts
+  * to host by buffering these packets in firmware/hardware for some
+  * predefined time. Received interrupt will be generated when one of the
+- * following events occur.
++ * following events occurs.
+  * a) Expiration of hardware timer whose expiration time is set to maximum
+  * coalescing delay of matching coalesce rule.
+- * b) Coalescing buffer in hardware reaches it's limit.
++ * b) Coalescing buffer in hardware reaches its limit.
+  * c) Packet doesn't match any of the configured coalesce rules.
+  *
+  * User needs to configure following parameters for creating a coalesce
+  * rule.
+  * a) Maximum coalescing delay
+  * b) List of packet patterns which needs to be matched
+- * c) Condition for coalescence. pattern 'match' or 'no match'
++ * c) Condition for coalescence: pattern 'match' or 'no match'
+  * Multiple such rules can be created.
+  */
+ 
+@@ -213,7 +213,7 @@
+ /**
+  * DOC: FILS shared key authentication offload
+  *
+- * FILS shared key authentication offload can be advertized by drivers by
++ * FILS shared key authentication offload can be advertised by drivers by
+  * setting @NL80211_EXT_FEATURE_FILS_SK_OFFLOAD flag. The drivers that support
+  * FILS shared key authentication offload should be able to construct the
+  * authentication and association frames for FILS shared key authentication and
+@@ -239,7 +239,7 @@
+  * The PMKSA can be maintained in userspace persistently so that it can be used
+  * later after reboots or wifi turn off/on also.
+  *
+- * %NL80211_ATTR_FILS_CACHE_ID is the cache identifier advertized by a FILS
++ * %NL80211_ATTR_FILS_CACHE_ID is the cache identifier advertised by a FILS
+  * capable AP supporting PMK caching. It specifies the scope within which the
+  * PMKSAs are cached in an ESS. %NL80211_CMD_SET_PMKSA and
+  * %NL80211_CMD_DEL_PMKSA are enhanced to allow support for PMKSA caching based
+@@ -290,12 +290,12 @@
+  * If the configuration needs to be applied for specific peer then the MAC
+  * address of the peer needs to be passed in %NL80211_ATTR_MAC, otherwise the
+  * configuration will be applied for all the connected peers in the vif except
+- * any peers that have peer specific configuration for the TID by default; if
+- * the %NL80211_TID_CONFIG_ATTR_OVERRIDE flag is set, peer specific values
++ * any peers that have peer-specific configuration for the TID by default; if
++ * the %NL80211_TID_CONFIG_ATTR_OVERRIDE flag is set, peer-specific values
+  * will be overwritten.
+  *
+- * All this configuration is valid only for STA's current connection
+- * i.e. the configuration will be reset to default when the STA connects back
++ * All this configuration is valid only for STA's current connection,
++ * i.e., the configuration will be reset to default when the STA connects back
+  * after disconnection/roaming, and this configuration will be cleared when
+  * the interface goes down.
+  */
+@@ -326,7 +326,7 @@
+ /**
+  * DOC: Multi-Link Operation
+  *
+- * In Multi-Link Operation, a connection between to MLDs utilizes multiple
++ * In Multi-Link Operation, a connection between two MLDs utilizes multiple
+  * links. To use this in nl80211, various commands and responses now need
+  * to or will include the new %NL80211_ATTR_MLO_LINKS attribute.
+  * Additionally, various commands that need to operate on a specific link
+@@ -335,6 +335,15 @@
+  */
+ 
+ /**
++ * DOC: OWE DH IE handling offload
++ *
++ * By setting @NL80211_EXT_FEATURE_OWE_OFFLOAD flag, drivers can indicate
++ * kernel/application space to avoid DH IE handling. When this flag is
++ * advertised, the driver/device will take care of DH IE inclusion and
++ * processing of peer DH IE to generate PMK.
++ */
++
++/**
+  * enum nl80211_commands - supported nl80211 commands
+  *
+  * @NL80211_CMD_UNSPEC: unspecified command to catch errors
+@@ -404,8 +413,8 @@
+  *	are like for %NL80211_CMD_SET_BEACON, and additionally parameters that
+  *	do not change are used, these include %NL80211_ATTR_BEACON_INTERVAL,
+  *	%NL80211_ATTR_DTIM_PERIOD, %NL80211_ATTR_SSID,
+- *	%NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHERS_PAIRWISE,
+- *	%NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS,
++ *	%NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
++ *	%NL80211_ATTR_CIPHER_SUITE_GROUP, %NL80211_ATTR_WPA_VERSIONS,
+  *	%NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY,
+  *	%NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_INACTIVITY_TIMEOUT,
+  *	%NL80211_ATTR_ACL_POLICY and %NL80211_ATTR_MAC_ADDRS.
+@@ -429,23 +438,19 @@
+  *	%NL80211_ATTR_REASON_CODE can optionally be used to specify which type
+  *	of disconnection indication should be sent to the station
+  *	(Deauthentication or Disassociation frame and reason code for that
+- *	frame).
++ *	frame). %NL80211_ATTR_MLO_LINK_ID can be used optionally to remove
++ *	stations connected and using at least that link as one of its links.
+  *
+  * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to
+- * 	destination %NL80211_ATTR_MAC on the interface identified by
+- * 	%NL80211_ATTR_IFINDEX.
++ *	destination %NL80211_ATTR_MAC on the interface identified by
++ *	%NL80211_ATTR_IFINDEX.
+  * @NL80211_CMD_SET_MPATH:  Set mesh path attributes for mesh path to
+- * 	destination %NL80211_ATTR_MAC on the interface identified by
+- * 	%NL80211_ATTR_IFINDEX.
++ *	destination %NL80211_ATTR_MAC on the interface identified by
++ *	%NL80211_ATTR_IFINDEX.
+  * @NL80211_CMD_NEW_MPATH: Create a new mesh path for the destination given by
+  *	%NL80211_ATTR_MAC via %NL80211_ATTR_MPATH_NEXT_HOP.
+  * @NL80211_CMD_DEL_MPATH: Delete a mesh path to the destination given by
+  *	%NL80211_ATTR_MAC.
+- * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the
+- *	interface identified by %NL80211_ATTR_IFINDEX.
+- * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC
+- *	or, if no MAC address given, all mesh paths, on the interface identified
+- *	by %NL80211_ATTR_IFINDEX.
+  * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by
+  *	%NL80211_ATTR_IFINDEX.
+  *
+@@ -466,15 +471,15 @@
+  *	after being queried by the kernel. CRDA replies by sending a regulatory
+  *	domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our
+  *	current alpha2 if it found a match. It also provides
+- * 	NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each
+- * 	regulatory rule is a nested set of attributes  given by
+- * 	%NL80211_ATTR_REG_RULE_FREQ_[START|END] and
+- * 	%NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by
+- * 	%NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and
+- * 	%NL80211_ATTR_REG_RULE_POWER_MAX_EIRP.
++ *	NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each
++ *	regulatory rule is a nested set of attributes  given by
++ *	%NL80211_ATTR_REG_RULE_FREQ_[START|END] and
++ *	%NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by
++ *	%NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and
++ *	%NL80211_ATTR_REG_RULE_POWER_MAX_EIRP.
+  * @NL80211_CMD_REQ_SET_REG: ask the wireless core to set the regulatory domain
+- * 	to the specified ISO/IEC 3166-1 alpha2 country code. The core will
+- * 	store this as a valid request and then query userspace for it.
++ *	to the specified ISO/IEC 3166-1 alpha2 country code. The core will
++ *	store this as a valid request and then query userspace for it.
+  *
+  * @NL80211_CMD_GET_MESH_CONFIG: Get mesh networking properties for the
+  *	interface identified by %NL80211_ATTR_IFINDEX
+@@ -512,7 +517,7 @@
+  *	%NL80211_ATTR_SCHED_SCAN_PLANS. If %NL80211_ATTR_SCHED_SCAN_PLANS is
+  *	not specified and only %NL80211_ATTR_SCHED_SCAN_INTERVAL is specified,
+  *	scheduled scan will run in an infinite loop with the specified interval.
+- *	These attributes are mutually exculsive,
++ *	These attributes are mutually exclusive,
+  *	i.e. NL80211_ATTR_SCHED_SCAN_INTERVAL must not be passed if
+  *	NL80211_ATTR_SCHED_SCAN_PLANS is defined.
+  *	If for some reason scheduled scan is aborted by the driver, all scan
+@@ -543,7 +548,7 @@
+  *	%NL80211_CMD_STOP_SCHED_SCAN command is received or when the interface
+  *	is brought down while a scheduled scan was running.
+  *
+- * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation
++ * @NL80211_CMD_GET_SURVEY: get survey results, e.g. channel occupation
+  *      or noise level
+  * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to
+  *	NL80211_CMD_GET_SURVEY and on the "scan" multicast group)
+@@ -554,40 +559,41 @@
+  *	using %NL80211_ATTR_SSID, %NL80211_ATTR_FILS_CACHE_ID,
+  *	%NL80211_ATTR_PMKID, and %NL80211_ATTR_PMK in case of FILS
+  *	authentication where %NL80211_ATTR_FILS_CACHE_ID is the identifier
+- *	advertized by a FILS capable AP identifying the scope of PMKSA in an
++ *	advertised by a FILS capable AP identifying the scope of PMKSA in an
+  *	ESS.
+  * @NL80211_CMD_DEL_PMKSA: Delete a PMKSA cache entry, using %NL80211_ATTR_MAC
+  *	(for the BSSID) and %NL80211_ATTR_PMKID or using %NL80211_ATTR_SSID,
+  *	%NL80211_ATTR_FILS_CACHE_ID, and %NL80211_ATTR_PMKID in case of FILS
+- *	authentication.
++ *	authentication. Additionally in case of SAE offload and OWE offloads
++ *	PMKSA entry can be deleted using %NL80211_ATTR_SSID.
+  * @NL80211_CMD_FLUSH_PMKSA: Flush all PMKSA cache entries.
+  *
+  * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain
+- * 	has been changed and provides details of the request information
+- * 	that caused the change such as who initiated the regulatory request
+- * 	(%NL80211_ATTR_REG_INITIATOR), the wiphy_idx
+- * 	(%NL80211_ATTR_REG_ALPHA2) on which the request was made from if
+- * 	the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or
+- * 	%NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain
+- * 	set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is
+- * 	%NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on
+- * 	to (%NL80211_ATTR_REG_ALPHA2).
++ *	has been changed and provides details of the request information
++ *	that caused the change such as who initiated the regulatory request
++ *	(%NL80211_ATTR_REG_INITIATOR), the wiphy_idx
++ *	(%NL80211_ATTR_REG_ALPHA2) on which the request was made from if
++ *	the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or
++ *	%NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain
++ *	set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is
++ *	%NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on
++ *	to (%NL80211_ATTR_REG_ALPHA2).
+  * @NL80211_CMD_REG_BEACON_HINT: indicates to userspace that an AP beacon
+- * 	has been found while world roaming thus enabling active scan or
+- * 	any mode of operation that initiates TX (beacons) on a channel
+- * 	where we would not have been able to do either before. As an example
+- * 	if you are world roaming (regulatory domain set to world or if your
+- * 	driver is using a custom world roaming regulatory domain) and while
+- * 	doing a passive scan on the 5 GHz band you find an AP there (if not
+- * 	on a DFS channel) you will now be able to actively scan for that AP
+- * 	or use AP mode on your card on that same channel. Note that this will
+- * 	never be used for channels 1-11 on the 2 GHz band as they are always
+- * 	enabled world wide. This beacon hint is only sent if your device had
+- * 	either disabled active scanning or beaconing on a channel. We send to
+- * 	userspace the wiphy on which we removed a restriction from
+- * 	(%NL80211_ATTR_WIPHY) and the channel on which this occurred
+- * 	before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER)
+- * 	the beacon hint was processed.
++ *	has been found while world roaming thus enabling active scan or
++ *	any mode of operation that initiates TX (beacons) on a channel
++ *	where we would not have been able to do either before. As an example
++ *	if you are world roaming (regulatory domain set to world or if your
++ *	driver is using a custom world roaming regulatory domain) and while
++ *	doing a passive scan on the 5 GHz band you find an AP there (if not
++ *	on a DFS channel) you will now be able to actively scan for that AP
++ *	or use AP mode on your card on that same channel. Note that this will
++ *	never be used for channels 1-11 on the 2 GHz band as they are always
++ *	enabled world wide. This beacon hint is only sent if your device had
++ *	either disabled active scanning or beaconing on a channel. We send to
++ *	userspace the wiphy on which we removed a restriction from
++ *	(%NL80211_ATTR_WIPHY) and the channel on which this occurred
++ *	before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER)
++ *	the beacon hint was processed.
+  *
+  * @NL80211_CMD_AUTHENTICATE: authentication request and notification.
+  *	This command is used both as a command (request to authenticate) and
+@@ -598,7 +604,7 @@
+  *	BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify
+  *	the SSID (mainly for association, but is included in authentication
+  *	request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ +
+- *	%NL80211_ATTR_WIPHY_FREQ_OFFSET is used to specify the frequence of the
++ *	%NL80211_ATTR_WIPHY_FREQ_OFFSET is used to specify the frequency of the
+  *	channel in MHz. %NL80211_ATTR_AUTH_TYPE is used to specify the
+  *	authentication type. %NL80211_ATTR_IE is used to define IEs
+  *	(VendorSpecificInfo, but also including RSN IE and FT IEs) to be added
+@@ -807,7 +813,7 @@
+  *	reached.
+  * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ
+  *	and the attributes determining channel width) the given interface
+- *	(identifed by %NL80211_ATTR_IFINDEX) shall operate on.
++ *	(identified by %NL80211_ATTR_IFINDEX) shall operate on.
+  *	In case multiple channels are supported by the device, the mechanism
+  *	with which it switches channels is implementation-defined.
+  *	When a monitor interface is given, it can only switch channel while
+@@ -879,7 +885,7 @@
+  *	inform userspace of the new replay counter.
+  *
+  * @NL80211_CMD_PMKSA_CANDIDATE: This is used as an event to inform userspace
+- *	of PMKSA caching dandidates.
++ *	of PMKSA caching candidates.
+  *
+  * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup).
+  *	In addition, this can be used as an event to request userspace to take
+@@ -915,7 +921,7 @@
+  *
+  * @NL80211_CMD_PROBE_CLIENT: Probe an associated station on an AP interface
+  *	by sending a null data frame to it and reporting when the frame is
+- *	acknowleged. This is used to allow timing out inactive clients. Uses
++ *	acknowledged. This is used to allow timing out inactive clients. Uses
+  *	%NL80211_ATTR_IFINDEX and %NL80211_ATTR_MAC. The command returns a
+  *	direct reply with an %NL80211_ATTR_COOKIE that is later used to match
+  *	up the event with the request. The event includes the same data and
+@@ -1109,7 +1115,7 @@
+  *	current configuration is not changed.  If it is present but
+  *	set to zero, the configuration is changed to don't-care
+  *	(i.e. the device can decide what to do).
+- * @NL80211_CMD_NAN_FUNC_MATCH: Notification sent when a match is reported.
++ * @NL80211_CMD_NAN_MATCH: Notification sent when a match is reported.
+  *	This will contain a %NL80211_ATTR_NAN_MATCH nested attribute and
+  *	%NL80211_ATTR_COOKIE.
+  *
+@@ -1126,11 +1132,15 @@
+  * @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously
+  *	configured PMK for the authenticator address identified by
+  *	%NL80211_ATTR_MAC.
+- * @NL80211_CMD_PORT_AUTHORIZED: An event that indicates an 802.1X FT roam was
+- *	completed successfully. Drivers that support 4 way handshake offload
+- *	should send this event after indicating 802.1X FT assocation with
+- *	%NL80211_CMD_ROAM. If the 4 way handshake failed %NL80211_CMD_DISCONNECT
+- *	should be indicated instead.
++ * @NL80211_CMD_PORT_AUTHORIZED: An event that indicates port is authorized and
++ *	open for regular data traffic. For STA/P2P-client, this event is sent
++ *	with AP MAC address and for AP/P2P-GO, the event carries the STA/P2P-
++ *	client MAC address.
++ *	Drivers that support 4 way handshake offload should send this event for
++ *	STA/P2P-client after successful 4-way HS or after 802.1X FT following
++ *	NL80211_CMD_CONNECT or NL80211_CMD_ROAM. Drivers using AP/P2P-GO 4-way
++ *	handshake offload should send this event on successful completion of
++ *	4-way handshake with the peer (STA/P2P-client).
+  * @NL80211_CMD_CONTROL_PORT_FRAME: Control Port (e.g. PAE) frame TX request
+  *	and RX notification.  This command is used both as a request to transmit
+  *	a control port frame and as a notification that a control port frame
+@@ -1314,6 +1324,11 @@
+  *	Multi-Link reconfiguration. %NL80211_ATTR_MLO_LINKS is used to provide
+  *	information about the removed STA MLD setup links.
+  *
++ * @NL80211_CMD_SET_TID_TO_LINK_MAPPING: Set the TID to Link Mapping for a
++ *      non-AP MLD station. The %NL80211_ATTR_MLO_TTLM_DLINK and
++ *      %NL80211_ATTR_MLO_TTLM_ULINK attributes are used to specify the
++ *      TID to Link mapping for downlink/uplink traffic.
++ *
+  * @NL80211_CMD_MAX: highest used command number
+  * @__NL80211_CMD_AFTER_LAST: internal use
+  */
+@@ -1569,6 +1584,8 @@ enum nl80211_commands {
+ 
+ 	NL80211_CMD_LINKS_REMOVED,
+ 
++	NL80211_CMD_SET_TID_TO_LINK_MAPPING,
++
+ 	/* add new commands above here */
+ 
+ 	/* used to define NL80211_CMD_MAX below */
+@@ -1693,21 +1710,21 @@ enum nl80211_commands {
+  *	(see &enum nl80211_plink_action).
+  * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path.
+  * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path
+- * 	info given for %NL80211_CMD_GET_MPATH, nested attribute described at
++ *	info given for %NL80211_CMD_GET_MPATH, nested attribute described at
+  *	&enum nl80211_mpath_info.
+  *
+  * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of
+  *      &enum nl80211_mntr_flags.
+  *
+  * @NL80211_ATTR_REG_ALPHA2: an ISO-3166-alpha2 country code for which the
+- * 	current regulatory domain should be set to or is already set to.
+- * 	For example, 'CR', for Costa Rica. This attribute is used by the kernel
+- * 	to query the CRDA to retrieve one regulatory domain. This attribute can
+- * 	also be used by userspace to query the kernel for the currently set
+- * 	regulatory domain. We chose an alpha2 as that is also used by the
+- * 	IEEE-802.11 country information element to identify a country.
+- * 	Users can also simply ask the wireless core to set regulatory domain
+- * 	to a specific alpha2.
++ *	current regulatory domain should be set to or is already set to.
++ *	For example, 'CR', for Costa Rica. This attribute is used by the kernel
++ *	to query the CRDA to retrieve one regulatory domain. This attribute can
++ *	also be used by userspace to query the kernel for the currently set
++ *	regulatory domain. We chose an alpha2 as that is also used by the
++ *	IEEE-802.11 country information element to identify a country.
++ *	Users can also simply ask the wireless core to set regulatory domain
++ *	to a specific alpha2.
+  * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory
+  *	rules.
+  *
+@@ -1750,9 +1767,9 @@ enum nl80211_commands {
+  * @NL80211_ATTR_BSS: scan result BSS
+  *
+  * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain
+- * 	currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_*
++ *	currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_*
+  * @NL80211_ATTR_REG_TYPE: indicates the type of the regulatory domain currently
+- * 	set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*)
++ *	set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*)
+  *
+  * @NL80211_ATTR_SUPPORTED_COMMANDS: wiphy attribute that specifies
+  *	an array of command numbers (i.e. a mapping index to command number)
+@@ -1771,15 +1788,15 @@ enum nl80211_commands {
+  *	a u32
+  *
+  * @NL80211_ATTR_FREQ_BEFORE: A channel which has suffered a regulatory change
+- * 	due to considerations from a beacon hint. This attribute reflects
+- * 	the state of the channel _before_ the beacon hint processing. This
+- * 	attributes consists of a nested attribute containing
+- * 	NL80211_FREQUENCY_ATTR_*
++ *	due to considerations from a beacon hint. This attribute reflects
++ *	the state of the channel _before_ the beacon hint processing. This
++ *	attributes consists of a nested attribute containing
++ *	NL80211_FREQUENCY_ATTR_*
+  * @NL80211_ATTR_FREQ_AFTER: A channel which has suffered a regulatory change
+- * 	due to considerations from a beacon hint. This attribute reflects
+- * 	the state of the channel _after_ the beacon hint processing. This
+- * 	attributes consists of a nested attribute containing
+- * 	NL80211_FREQUENCY_ATTR_*
++ *	due to considerations from a beacon hint. This attribute reflects
++ *	the state of the channel _after_ the beacon hint processing. This
++ *	attributes consists of a nested attribute containing
++ *	NL80211_FREQUENCY_ATTR_*
+  *
+  * @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported
+  *	cipher suites
+@@ -1826,7 +1843,7 @@ enum nl80211_commands {
+  *	using %CMD_CONTROL_PORT_FRAME.  If control port routing over NL80211 is
+  *	to be used then userspace must also use the %NL80211_ATTR_SOCKET_OWNER
+  *	flag. When used with %NL80211_ATTR_CONTROL_PORT_NO_PREAUTH, pre-auth
+- *	frames are not forwared over the control port.
++ *	frames are not forwarded over the control port.
+  *
+  * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver.
+  *	We recommend using nested, driver-specific attributes within this.
+@@ -1840,12 +1857,6 @@ enum nl80211_commands {
+  *	that protected APs should be used. This is also used with NEW_BEACON to
+  *	indicate that the BSS is to use protection.
+  *
+- * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT, ASSOCIATE, and NEW_BEACON
+- *	to indicate which unicast key ciphers will be used with the connection
+- *	(an array of u32).
+- * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT, ASSOCIATE, and NEW_BEACON to
+- *	indicate which group key cipher will be used with the connection (a
+- *	u32).
+  * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT, ASSOCIATE, and NEW_BEACON to
+  *	indicate which WPA version(s) the AP we want to associate with is using
+  *	(a u32 with flags from &enum nl80211_wpa_versions).
+@@ -1876,6 +1887,7 @@ enum nl80211_commands {
+  *	with %NL80211_KEY_* sub-attributes
+  *
+  * @NL80211_ATTR_PID: Process ID of a network namespace.
++ * @NL80211_ATTR_NETNS_FD: File descriptor of a network namespace.
+  *
+  * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for
+  *	dumps. This number increases whenever the object list being
+@@ -1930,6 +1942,7 @@ enum nl80211_commands {
+  *
+  * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was
+  *	acknowledged by the recipient.
++ * @NL80211_ATTR_ACK_SIGNAL: Station's ack signal strength (s32)
+  *
+  * @NL80211_ATTR_PS_STATE: powersave state, using &enum nl80211_ps_state values.
+  *
+@@ -1963,10 +1976,10 @@ enum nl80211_commands {
+  *	bit. Depending on which antennas are selected in the bitmap, 802.11n
+  *	drivers can derive which chainmasks to use (if all antennas belonging to
+  *	a particular chain are disabled this chain should be disabled) and if
+- *	a chain has diversity antennas wether diversity should be used or not.
++ *	a chain has diversity antennas whether diversity should be used or not.
+  *	HT capabilities (STBC, TX Beamforming, Antenna selection) can be
+  *	derived from the available chains after applying the antenna mask.
+- *	Non-802.11n drivers can derive wether to use diversity or not.
++ *	Non-802.11n drivers can derive whether to use diversity or not.
+  *	Drivers may reject configurations or RX/TX mask combinations they cannot
+  *	support by returning -EINVAL.
+  *
+@@ -2039,6 +2052,10 @@ enum nl80211_commands {
+  * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported
+  *	interface combinations. In each nested item, it contains attributes
+  *	defined in &enum nl80211_if_combination_attrs.
++ *	If the wiphy uses multiple radios (@NL80211_ATTR_WIPHY_RADIOS is set),
++ *	this attribute contains the interface combinations of the first radio.
++ *	See @NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS for the global wiphy
++ *	combinations for the sum of all radios.
+  * @NL80211_ATTR_SOFTWARE_IFTYPES: Nested attribute (just like
+  *	%NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that
+  *	are managed in software: interfaces of these types aren't subject to
+@@ -2127,6 +2144,9 @@ enum nl80211_commands {
+  * @NL80211_ATTR_DISABLE_HE: Force HE capable interfaces to disable
+  *      this feature during association. This is a flag attribute.
+  *	Currently only supported in mac80211 drivers.
++ * @NL80211_ATTR_DISABLE_EHT: Force EHT capable interfaces to disable
++ *      this feature during association. This is a flag attribute.
++ *	Currently only supported in mac80211 drivers.
+  * @NL80211_ATTR_HT_CAPABILITY_MASK: Specify which bits of the
+  *      ATTR_HT_CAPABILITY to which attention should be paid.
+  *      Currently, only mac80211 NICs support this feature.
+@@ -2136,6 +2156,12 @@ enum nl80211_commands {
+  *      All values are treated as suggestions and may be ignored
+  *      by the driver as required.  The actual values may be seen in
+  *      the station debugfs ht_caps file.
++ * @NL80211_ATTR_VHT_CAPABILITY_MASK: Specify which bits of the
++ *      ATTR_VHT_CAPABILITY to which attention should be paid.
++ *      Currently, only mac80211 NICs support this feature.
++ *      All values are treated as suggestions and may be ignored
++ *      by the driver as required.  The actual values may be seen in
++ *      the station debugfs vht_caps file.
+  *
+  * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country
+  *    abides to when initiating radiation on DFS channels. A country maps
+@@ -2394,7 +2420,7 @@ enum nl80211_commands {
+  *	scheduled scan is started.  Or the delay before a WoWLAN
+  *	net-detect scan is started, counting from the moment the
+  *	system is suspended.  This value is a u32, in seconds.
+-
++ *
+  * @NL80211_ATTR_REG_INDOOR: flag attribute, if set indicates that the device
+  *      is operating in an indoor environment.
+  *
+@@ -2536,7 +2562,7 @@ enum nl80211_commands {
+  *	from successful FILS authentication and is used with
+  *	%NL80211_CMD_CONNECT.
+  *
+- * @NL80211_ATTR_FILS_CACHE_ID: A 2-octet identifier advertized by a FILS AP
++ * @NL80211_ATTR_FILS_CACHE_ID: A 2-octet identifier advertised by a FILS AP
+  *	identifying the scope of PMKSAs. This is used with
+  *	@NL80211_CMD_SET_PMKSA and @NL80211_CMD_DEL_PMKSA.
+  *
+@@ -2690,11 +2716,13 @@ enum nl80211_commands {
+  *
+  * @NL80211_ATTR_FILS_DISCOVERY: Optional parameter to configure FILS
+  *	discovery. It is a nested attribute, see
+- *	&enum nl80211_fils_discovery_attributes.
++ *	&enum nl80211_fils_discovery_attributes. Userspace should pass an empty
++ *	nested attribute to disable this feature and delete the templates.
+  *
+  * @NL80211_ATTR_UNSOL_BCAST_PROBE_RESP: Optional parameter to configure
+  *	unsolicited broadcast probe response. It is a nested attribute, see
+- *	&enum nl80211_unsol_bcast_probe_resp_attributes.
++ *	&enum nl80211_unsol_bcast_probe_resp_attributes. Userspace should pass an empty
++ *	nested attribute to disable this feature and delete the templates.
+  *
+  * @NL80211_ATTR_S1G_CAPABILITY: S1G Capability information element (from
+  *	association request when used with NL80211_CMD_NEW_STATION)
+@@ -2815,6 +2843,34 @@ enum nl80211_commands {
+  * @NL80211_ATTR_MLO_LINK_DISABLED: Flag attribute indicating that the link is
+  *	disabled.
+  *
++ * @NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA: Include BSS usage data, i.e.
++ *	include BSSes that can only be used in restricted scenarios and/or
++ *	cannot be used at all.
++ *
++ * @NL80211_ATTR_MLO_TTLM_DLINK: Binary attribute specifying the downlink TID to
++ *      link mapping. The length is 8 * sizeof(u16). For each TID the link
++ *      mapping is as defined in section 9.4.2.314 (TID-To-Link Mapping element)
++ *      in Draft P802.11be_D4.0.
++ * @NL80211_ATTR_MLO_TTLM_ULINK: Binary attribute specifying the uplink TID to
++ *      link mapping. The length is 8 * sizeof(u16). For each TID the link
++ *      mapping is as defined in section 9.4.2.314 (TID-To-Link Mapping element)
++ *      in Draft P802.11be_D4.0.
++ *
++ * @NL80211_ATTR_ASSOC_SPP_AMSDU: flag attribute used with
++ *	%NL80211_CMD_ASSOCIATE indicating the SPP A-MSDUs
++ *	are used on this connection
++ *
++ * @NL80211_ATTR_WIPHY_RADIOS: Nested attribute describing physical radios
++ *	belonging to this wiphy. See &enum nl80211_wiphy_radio_attrs.
++ *
++ * @NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS: Nested attribute listing the
++ *	supported interface combinations for all radios combined. In each
++ *	nested item, it contains attributes defined in
++ *	&enum nl80211_if_combination_attrs.
++ *
++ * @NL80211_ATTR_VIF_RADIO_MASK: Bitmask of allowed radios (u32).
++ *	A value of 0 means all radios.
++ *
+  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
+  * @NL80211_ATTR_MAX: highest attribute number currently defined
+  * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -3353,6 +3409,18 @@ enum nl80211_attrs {
+ 
+ 	NL80211_ATTR_MLO_LINK_DISABLED,
+ 
++	NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA,
++
++	NL80211_ATTR_MLO_TTLM_DLINK,
++	NL80211_ATTR_MLO_TTLM_ULINK,
++
++	NL80211_ATTR_ASSOC_SPP_AMSDU,
++
++	NL80211_ATTR_WIPHY_RADIOS,
++	NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS,
++
++	NL80211_ATTR_VIF_RADIO_MASK,
++
+ 	/* add attributes here, update the policy in nl80211.c */
+ 
+ 	__NL80211_ATTR_AFTER_LAST,
+@@ -3493,6 +3561,7 @@ enum nl80211_iftype {
+  * @NL80211_STA_FLAG_ASSOCIATED: station is associated; used with drivers
+  *	that support %NL80211_FEATURE_FULL_AP_CLIENT_STATE to transition a
+  *	previously added station into associated state
++ * @NL80211_STA_FLAG_SPP_AMSDU: station supports SPP A-MSDUs
+  * @NL80211_STA_FLAG_MAX: highest station flag number currently defined
+  * @__NL80211_STA_FLAG_AFTER_LAST: internal use
+  */
+@@ -3505,6 +3574,7 @@ enum nl80211_sta_flags {
+ 	NL80211_STA_FLAG_AUTHENTICATED,
+ 	NL80211_STA_FLAG_TDLS_PEER,
+ 	NL80211_STA_FLAG_ASSOCIATED,
++	NL80211_STA_FLAG_SPP_AMSDU,
+ 
+ 	/* keep last */
+ 	__NL80211_STA_FLAG_AFTER_LAST,
+@@ -3515,7 +3585,7 @@ enum nl80211_sta_flags {
+  * enum nl80211_sta_p2p_ps_status - station support of P2P PS
+  *
+  * @NL80211_P2P_PS_UNSUPPORTED: station doesn't support P2P PS mechanism
+- * @@NL80211_P2P_PS_SUPPORTED: station supports P2P PS mechanism
++ * @NL80211_P2P_PS_SUPPORTED: station supports P2P PS mechanism
+  * @NUM_NL80211_P2P_PS_STATUS: number of values
+  */
+ enum nl80211_sta_p2p_ps_status {
+@@ -3553,9 +3623,9 @@ enum nl80211_he_gi {
+ 
+ /**
+  * enum nl80211_he_ltf - HE long training field
+- * @NL80211_RATE_INFO_HE_1xLTF: 3.2 usec
+- * @NL80211_RATE_INFO_HE_2xLTF: 6.4 usec
+- * @NL80211_RATE_INFO_HE_4xLTF: 12.8 usec
++ * @NL80211_RATE_INFO_HE_1XLTF: 3.2 usec
++ * @NL80211_RATE_INFO_HE_2XLTF: 6.4 usec
++ * @NL80211_RATE_INFO_HE_4XLTF: 12.8 usec
+  */
+ enum nl80211_he_ltf {
+ 	NL80211_RATE_INFO_HE_1XLTF,
+@@ -3670,7 +3740,7 @@ enum nl80211_eht_ru_alloc {
+  * @NL80211_RATE_INFO_HE_GI: HE guard interval identifier
+  *	(u8, see &enum nl80211_he_gi)
+  * @NL80211_RATE_INFO_HE_DCM: HE DCM value (u8, 0/1)
+- * @NL80211_RATE_INFO_RU_ALLOC: HE RU allocation, if not present then
++ * @NL80211_RATE_INFO_HE_RU_ALLOC: HE RU allocation, if not present then
+  *	non-OFDMA was used (u8, see &enum nl80211_he_ru_alloc)
+  * @NL80211_RATE_INFO_320_MHZ_WIDTH: 320 MHz bitrate
+  * @NL80211_RATE_INFO_EHT_MCS: EHT MCS index (u8, 0-15)
+@@ -3773,7 +3843,7 @@ enum nl80211_sta_bss_param {
+  *	(u64, to this station)
+  * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+  * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+- * 	containing info as possible, see &enum nl80211_rate_info
++ *	containing info as possible, see &enum nl80211_rate_info
+  * @NL80211_STA_INFO_RX_PACKETS: total received packet (MSDUs and MMPDUs)
+  *	(u32, from this station)
+  * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (MSDUs and MMPDUs)
+@@ -3802,8 +3872,8 @@ enum nl80211_sta_bss_param {
+  *	Contains a nested array of signal strength attributes (u8, dBm)
+  * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
+  *	Same format as NL80211_STA_INFO_CHAIN_SIGNAL.
+- * @NL80211_STA_EXPECTED_THROUGHPUT: expected throughput considering also the
+- *	802.11 header (u32, kbps)
++ * @NL80211_STA_INFO_EXPECTED_THROUGHPUT: expected throughput considering also
++ *	the 802.11 header (u32, kbps)
+  * @NL80211_STA_INFO_RX_DROP_MISC: RX packets dropped for unspecified reasons
+  *	(u64)
+  * @NL80211_STA_INFO_BEACON_RX: number of beacons received from this peer (u64)
+@@ -3989,7 +4059,7 @@ enum nl80211_mpath_flags {
+  * @NL80211_MPATH_INFO_METRIC: metric (cost) of this mesh path
+  * @NL80211_MPATH_INFO_EXPTIME: expiration time for the path, in msec from now
+  * @NL80211_MPATH_INFO_FLAGS: mesh path flags, enumerated in
+- * 	&enum nl80211_mpath_flags;
++ *	&enum nl80211_mpath_flags;
+  * @NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: total path discovery timeout, in msec
+  * @NL80211_MPATH_INFO_DISCOVERY_RETRIES: mesh path discovery retries
+  * @NL80211_MPATH_INFO_HOP_COUNT: hop count to destination
+@@ -4129,7 +4199,7 @@ enum nl80211_band_attr {
+  * @NL80211_WMMR_CW_MAX: Maximum contention window slot.
+  * @NL80211_WMMR_AIFSN: Arbitration Inter Frame Space.
+  * @NL80211_WMMR_TXOP: Maximum allowed tx operation time.
+- * @nl80211_WMMR_MAX: highest possible wmm rule.
++ * @NL80211_WMMR_MAX: highest possible wmm rule.
+  * @__NL80211_WMMR_LAST: Internal use.
+  */
+ enum nl80211_wmm_rule {
+@@ -4151,15 +4221,16 @@ enum nl80211_wmm_rule {
+  * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current
+  *	regulatory domain.
+  * @NL80211_FREQUENCY_ATTR_NO_IR: no mechanisms that initiate radiation
+- * 	are permitted on this channel, this includes sending probe
+- * 	requests, or modes of operation that require beaconing.
++ *	are permitted on this channel, this includes sending probe
++ *	requests, or modes of operation that require beaconing.
++ * @__NL80211_FREQUENCY_ATTR_NO_IBSS: obsolete, same as _NO_IR
+  * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory
+  *	on this channel in current regulatory domain.
+  * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm
+  *	(100 * dBm).
+  * @NL80211_FREQUENCY_ATTR_DFS_STATE: current state for DFS
+  *	(enum nl80211_dfs_state)
+- * @NL80211_FREQUENCY_ATTR_DFS_TIME: time in miliseconds for how long
++ * @NL80211_FREQUENCY_ATTR_DFS_TIME: time in milliseconds for how long
+  *	this channel is in this DFS state.
+  * @NL80211_FREQUENCY_ATTR_NO_HT40_MINUS: HT40- isn't possible with this
+  *	channel as the control channel
+@@ -4213,6 +4284,21 @@ enum nl80211_wmm_rule {
+  *	as the primary or any of the secondary channels isn't possible
+  * @NL80211_FREQUENCY_ATTR_NO_EHT: EHT operation is not allowed on this channel
+  *	in current regulatory domain.
++ * @NL80211_FREQUENCY_ATTR_PSD: Power spectral density (in dBm) that
++ *	is allowed on this channel in current regulatory domain.
++ * @NL80211_FREQUENCY_ATTR_DFS_CONCURRENT: Operation on this channel is
++ *	allowed for peer-to-peer or adhoc communication under the control
++ *	of a DFS master which operates on the same channel (FCC-594280 D01
++ *	Section B.3). Should be used together with %NL80211_RRF_DFS only.
++ * @NL80211_FREQUENCY_ATTR_NO_6GHZ_VLP_CLIENT: Client connection to VLP AP
++ *	not allowed using this channel
++ * @NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT: Client connection to AFC AP
++ *	not allowed using this channel
++ * @NL80211_FREQUENCY_ATTR_CAN_MONITOR: This channel can be used in monitor
++ *	mode despite other (regulatory) restrictions, even if the channel is
++ *	otherwise completely disabled.
++ * @NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP: This channel can be used for a
++ *	very low power (VLP) AP, despite being NO_IR.
+  * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
+  *	currently defined
+  * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
+@@ -4251,6 +4337,12 @@ enum nl80211_frequency_attr {
+ 	NL80211_FREQUENCY_ATTR_16MHZ,
+ 	NL80211_FREQUENCY_ATTR_NO_320MHZ,
+ 	NL80211_FREQUENCY_ATTR_NO_EHT,
++	NL80211_FREQUENCY_ATTR_PSD,
++	NL80211_FREQUENCY_ATTR_DFS_CONCURRENT,
++	NL80211_FREQUENCY_ATTR_NO_6GHZ_VLP_CLIENT,
++	NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT,
++	NL80211_FREQUENCY_ATTR_CAN_MONITOR,
++	NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP,
+ 
+ 	/* keep last */
+ 	__NL80211_FREQUENCY_ATTR_AFTER_LAST,
+@@ -4263,6 +4355,10 @@ enum nl80211_frequency_attr {
+ #define NL80211_FREQUENCY_ATTR_NO_IR		NL80211_FREQUENCY_ATTR_NO_IR
+ #define NL80211_FREQUENCY_ATTR_GO_CONCURRENT \
+ 					NL80211_FREQUENCY_ATTR_IR_CONCURRENT
++#define NL80211_FREQUENCY_ATTR_NO_UHB_VLP_CLIENT \
++	NL80211_FREQUENCY_ATTR_NO_6GHZ_VLP_CLIENT
++#define NL80211_FREQUENCY_ATTR_NO_UHB_AFC_CLIENT \
++	NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT
+ 
+ /**
+  * enum nl80211_bitrate_attr - bitrate attributes
+@@ -4285,16 +4381,16 @@ enum nl80211_bitrate_attr {
+ };
+ 
+ /**
+- * enum nl80211_initiator - Indicates the initiator of a reg domain request
++ * enum nl80211_reg_initiator - Indicates the initiator of a reg domain request
+  * @NL80211_REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world
+- * 	regulatory domain.
++ *	regulatory domain.
+  * @NL80211_REGDOM_SET_BY_USER: User asked the wireless core to set the
+- * 	regulatory domain.
++ *	regulatory domain.
+  * @NL80211_REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the
+- * 	wireless core it thinks its knows the regulatory domain we should be in.
++ *	wireless core it thinks its knows the regulatory domain we should be in.
+  * @NL80211_REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an
+- * 	802.11 country information element with regulatory information it
+- * 	thinks we should consider. cfg80211 only processes the country
++ *	802.11 country information element with regulatory information it
++ *	thinks we should consider. cfg80211 only processes the country
+  *	code from the IE, and relies on the regulatory domain information
+  *	structure passed by userspace (CRDA) from our wireless-regdb.
+  *	If a channel is enabled but the country code indicates it should
+@@ -4313,11 +4409,11 @@ enum nl80211_reg_initiator {
+  *	to a specific country. When this is set you can count on the
+  *	ISO / IEC 3166 alpha2 country code being valid.
+  * @NL80211_REGDOM_TYPE_WORLD: the regulatory set domain is the world regulatory
+- * 	domain.
++ *	domain.
+  * @NL80211_REGDOM_TYPE_CUSTOM_WORLD: the regulatory domain set is a custom
+- * 	driver specific world regulatory domain. These do not apply system-wide
+- * 	and are only applicable to the individual devices which have requested
+- * 	them to be applied.
++ *	driver specific world regulatory domain. These do not apply system-wide
++ *	and are only applicable to the individual devices which have requested
++ *	them to be applied.
+  * @NL80211_REGDOM_TYPE_INTERSECTION: the regulatory domain set is the product
+  *	of an intersection between two regulatory domains -- the previously
+  *	set regulatory domain on the system and the last accepted regulatory
+@@ -4334,23 +4430,25 @@ enum nl80211_reg_type {
+  * enum nl80211_reg_rule_attr - regulatory rule attributes
+  * @__NL80211_REG_RULE_ATTR_INVALID: attribute number 0 is reserved
+  * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional
+- * 	considerations for a given frequency range. These are the
+- * 	&enum nl80211_reg_rule_flags.
++ *	considerations for a given frequency range. These are the
++ *	&enum nl80211_reg_rule_flags.
+  * @NL80211_ATTR_FREQ_RANGE_START: starting frequencry for the regulatory
+- * 	rule in KHz. This is not a center of frequency but an actual regulatory
+- * 	band edge.
++ *	rule in KHz. This is not a center of frequency but an actual regulatory
++ *	band edge.
+  * @NL80211_ATTR_FREQ_RANGE_END: ending frequency for the regulatory rule
+- * 	in KHz. This is not a center a frequency but an actual regulatory
+- * 	band edge.
++ *	in KHz. This is not a center a frequency but an actual regulatory
++ *	band edge.
+  * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this
+  *	frequency range, in KHz.
+  * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain
+- * 	for a given frequency range. The value is in mBi (100 * dBi).
+- * 	If you don't have one then don't send this.
++ *	for a given frequency range. The value is in mBi (100 * dBi).
++ *	If you don't have one then don't send this.
+  * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for
+- * 	a given frequency range. The value is in mBm (100 * dBm).
++ *	a given frequency range. The value is in mBm (100 * dBm).
+  * @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds.
+  *	If not present or 0 default CAC time will be used.
++ * @NL80211_ATTR_POWER_RULE_PSD: power spectral density (in dBm).
++ *	This could be negative.
+  * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number
+  *	currently defined
+  * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use
+@@ -4368,6 +4466,8 @@ enum nl80211_reg_rule_attr {
+ 
+ 	NL80211_ATTR_DFS_CAC_TIME,
+ 
++	NL80211_ATTR_POWER_RULE_PSD,
++
+ 	/* keep last */
+ 	__NL80211_REG_RULE_ATTR_AFTER_LAST,
+ 	NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
+@@ -4396,14 +4496,7 @@ enum nl80211_reg_rule_attr {
+  *	value as specified by &struct nl80211_bss_select_rssi_adjust.
+  * @NL80211_SCHED_SCAN_MATCH_ATTR_BSSID: BSSID to be used for matching
+  *	(this cannot be used together with SSID).
+- * @NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI: Nested attribute that carries the
+- *	band specific minimum rssi thresholds for the bands defined in
+- *	enum nl80211_band. The minimum rssi threshold value(s32) specific to a
+- *	band shall be encapsulated in attribute with type value equals to one
+- *	of the NL80211_BAND_* defined in enum nl80211_band. For example, the
+- *	minimum rssi threshold value for 2.4GHZ band shall be encapsulated
+- *	within an attribute of type NL80211_BAND_2GHZ. And one or more of such
+- *	attributes will be nested within this attribute.
++ * @NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI: Obsolete
+  * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
+  *	attribute number currently defined
+  * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
+@@ -4416,7 +4509,7 @@ enum nl80211_sched_scan_match_attr {
+ 	NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI,
+ 	NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST,
+ 	NL80211_SCHED_SCAN_MATCH_ATTR_BSSID,
+-	NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI,
++	NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI, /* obsolete */
+ 
+ 	/* keep last */
+ 	__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
+@@ -4438,8 +4531,9 @@ enum nl80211_sched_scan_match_attr {
+  * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links
+  * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links
+  * @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed,
+- * 	this includes probe requests or modes of operation that require
+- * 	beaconing.
++ *	this includes probe requests or modes of operation that require
++ *	beaconing.
++ * @__NL80211_RRF_NO_IBSS: obsolete, same as NO_IR
+  * @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.
+@@ -4451,6 +4545,15 @@ enum nl80211_sched_scan_match_attr {
+  * @NL80211_RRF_NO_HE: HE operation not allowed
+  * @NL80211_RRF_NO_320MHZ: 320MHz operation not allowed
+  * @NL80211_RRF_NO_EHT: EHT operation not allowed
++ * @NL80211_RRF_PSD: Ruleset has power spectral density value
++ * @NL80211_RRF_DFS_CONCURRENT: Operation on this channel is allowed for
++ *	peer-to-peer or adhoc communication under the control of a DFS master
++ *	which operates on the same channel (FCC-594280 D01 Section B.3).
++ *	Should be used together with %NL80211_RRF_DFS only.
++ * @NL80211_RRF_NO_6GHZ_VLP_CLIENT: Client connection to VLP AP not allowed
++ * @NL80211_RRF_NO_6GHZ_AFC_CLIENT: Client connection to AFC AP not allowed
++ * @NL80211_RRF_ALLOW_6GHZ_VLP_AP: Very low power (VLP) AP can be permitted
++ *	despite NO_IR configuration.
+  */
+ enum nl80211_reg_rule_flags {
+ 	NL80211_RRF_NO_OFDM		= 1<<0,
+@@ -4471,6 +4574,11 @@ enum nl80211_reg_rule_flags {
+ 	NL80211_RRF_NO_HE		= 1<<17,
+ 	NL80211_RRF_NO_320MHZ		= 1<<18,
+ 	NL80211_RRF_NO_EHT		= 1<<19,
++	NL80211_RRF_PSD			= 1<<20,
++	NL80211_RRF_DFS_CONCURRENT	= 1<<21,
++	NL80211_RRF_NO_6GHZ_VLP_CLIENT	= 1<<22,
++	NL80211_RRF_NO_6GHZ_AFC_CLIENT	= 1<<23,
++	NL80211_RRF_ALLOW_6GHZ_VLP_AP	= 1<<24,
+ };
+ 
+ #define NL80211_RRF_PASSIVE_SCAN	NL80211_RRF_NO_IR
+@@ -4479,6 +4587,8 @@ enum nl80211_reg_rule_flags {
+ #define NL80211_RRF_NO_HT40		(NL80211_RRF_NO_HT40MINUS |\
+ 					 NL80211_RRF_NO_HT40PLUS)
+ #define NL80211_RRF_GO_CONCURRENT	NL80211_RRF_IR_CONCURRENT
++#define NL80211_RRF_NO_UHB_VLP_CLIENT	NL80211_RRF_NO_6GHZ_VLP_CLIENT
++#define NL80211_RRF_NO_UHB_AFC_CLIENT	NL80211_RRF_NO_6GHZ_AFC_CLIENT
+ 
+ /* For backport compatibility with older userspace */
+ #define NL80211_RRF_NO_IR_ALL		(NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS)
+@@ -4593,6 +4703,7 @@ enum nl80211_survey_info {
+  *	overrides all other flags.
+  * @NL80211_MNTR_FLAG_ACTIVE: use the configured MAC address
+  *	and ACK incoming unicast packets.
++ * @NL80211_MNTR_FLAG_SKIP_TX: do not pass local tx packets
+  *
+  * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use
+  * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag
+@@ -4605,6 +4716,7 @@ enum nl80211_mntr_flags {
+ 	NL80211_MNTR_FLAG_OTHER_BSS,
+ 	NL80211_MNTR_FLAG_COOK_FRAMES,
+ 	NL80211_MNTR_FLAG_ACTIVE,
++	NL80211_MNTR_FLAG_SKIP_TX,
+ 
+ 	/* keep last */
+ 	__NL80211_MNTR_FLAG_AFTER_LAST,
+@@ -4625,8 +4737,8 @@ enum nl80211_mntr_flags {
+  *	alternate between Active and Doze states, but may not wake up
+  *	for neighbor's beacons.
+  *
+- * @__NL80211_MESH_POWER_AFTER_LAST - internal use
+- * @NL80211_MESH_POWER_MAX - highest possible power save level
++ * @__NL80211_MESH_POWER_AFTER_LAST: internal use
++ * @NL80211_MESH_POWER_MAX: highest possible power save level
+  */
+ 
+ enum nl80211_mesh_power_mode {
+@@ -5008,6 +5120,36 @@ enum nl80211_bss_scan_width {
+ };
+ 
+ /**
++ * enum nl80211_bss_use_for - bitmap indicating possible BSS use
++ * @NL80211_BSS_USE_FOR_NORMAL: Use this BSS for normal "connection",
++ *	including IBSS/MBSS depending on the type.
++ * @NL80211_BSS_USE_FOR_MLD_LINK: This BSS can be used as a link in an
++ *	MLO connection. Note that for an MLO connection, all links including
++ *	the assoc link must have this flag set, and the assoc link must
++ *	additionally have %NL80211_BSS_USE_FOR_NORMAL set.
++ */
++enum nl80211_bss_use_for {
++	NL80211_BSS_USE_FOR_NORMAL = 1 << 0,
++	NL80211_BSS_USE_FOR_MLD_LINK = 1 << 1,
++};
++
++/**
++ * enum nl80211_bss_cannot_use_reasons - reason(s) connection to a
++ *	BSS isn't possible
++ * @NL80211_BSS_CANNOT_USE_NSTR_NONPRIMARY: NSTR nonprimary links aren't
++ *	supported by the device, and this BSS entry represents one.
++ * @NL80211_BSS_CANNOT_USE_6GHZ_PWR_MISMATCH: STA is not supporting
++ *	the AP power type (SP, VLP, AP) that the AP uses.
++ */
++enum nl80211_bss_cannot_use_reasons {
++	NL80211_BSS_CANNOT_USE_NSTR_NONPRIMARY	= 1 << 0,
++	NL80211_BSS_CANNOT_USE_6GHZ_PWR_MISMATCH	= 1 << 1,
++};
++
++#define NL80211_BSS_CANNOT_USE_UHB_PWR_MISMATCH \
++	NL80211_BSS_CANNOT_USE_6GHZ_PWR_MISMATCH
++
++/**
+  * enum nl80211_bss - netlink attributes for a BSS
+  *
+  * @__NL80211_BSS_INVALID: invalid
+@@ -5038,7 +5180,7 @@ enum nl80211_bss_scan_width {
+  *	elements from a Beacon frame (bin); not present if no Beacon frame has
+  *	yet been received
+  * @NL80211_BSS_CHAN_WIDTH: channel width of the control channel
+- *	(u32, enum nl80211_bss_scan_width)
++ *	(u32, enum nl80211_bss_scan_width) - No longer used!
+  * @NL80211_BSS_BEACON_TSF: TSF of the last received beacon (u64)
+  *	(not present if no beacon frame has been received yet)
+  * @NL80211_BSS_PRESP_DATA: the data in @NL80211_BSS_INFORMATION_ELEMENTS and
+@@ -5059,6 +5201,14 @@ enum nl80211_bss_scan_width {
+  * @NL80211_BSS_FREQUENCY_OFFSET: frequency offset in KHz
+  * @NL80211_BSS_MLO_LINK_ID: MLO link ID of the BSS (u8).
+  * @NL80211_BSS_MLD_ADDR: MLD address of this BSS if connected to it.
++ * @NL80211_BSS_USE_FOR: u32 bitmap attribute indicating what the BSS can be
++ *	used for, see &enum nl80211_bss_use_for.
++ * @NL80211_BSS_CANNOT_USE_REASONS: Indicates the reason that this BSS cannot
++ *	be used for all or some of the possible uses by the device reporting it,
++ *	even though its presence was detected.
++ *	This is a u64 attribute containing a bitmap of values from
++ *	&enum nl80211_cannot_use_reasons, note that the attribute may be missing
++ *	if no reasons are specified.
+  * @__NL80211_BSS_AFTER_LAST: internal
+  * @NL80211_BSS_MAX: highest BSS attribute
+  */
+@@ -5086,6 +5236,8 @@ enum nl80211_bss {
+ 	NL80211_BSS_FREQUENCY_OFFSET,
+ 	NL80211_BSS_MLO_LINK_ID,
+ 	NL80211_BSS_MLD_ADDR,
++	NL80211_BSS_USE_FOR,
++	NL80211_BSS_CANNOT_USE_REASONS,
+ 
+ 	/* keep last */
+ 	__NL80211_BSS_AFTER_LAST,
+@@ -5434,7 +5586,7 @@ enum nl80211_tx_rate_setting {
+  *	(%NL80211_TID_CONFIG_ATTR_TIDS, %NL80211_TID_CONFIG_ATTR_OVERRIDE).
+  * @NL80211_TID_CONFIG_ATTR_PEER_SUPP: same as the previous per-vif one, but
+  *	per peer instead.
+- * @NL80211_TID_CONFIG_ATTR_OVERRIDE: flag attribue, if set indicates
++ * @NL80211_TID_CONFIG_ATTR_OVERRIDE: flag attribute, if set indicates
+  *	that the new configuration overrides all previous peer
+  *	configurations, otherwise previous peer specific configurations
+  *	should be left untouched.
+@@ -5606,7 +5758,7 @@ struct nl80211_pattern_support {
+  *	"TCP connection wakeup" for more details. This is a nested attribute
+  *	containing the exact information for establishing and keeping alive
+  *	the TCP connection.
+- * @NL80211_WOWLAN_TRIG_TCP_WAKEUP_MATCH: For wakeup reporting only, the
++ * @NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH: For wakeup reporting only, the
+  *	wakeup packet was received on the TCP connection
+  * @NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST: For wakeup reporting only, the
+  *	TCP connection was lost or failed to be established
+@@ -5635,6 +5787,8 @@ struct nl80211_pattern_support {
+  *	%NL80211_ATTR_SCAN_FREQUENCIES contains more than one
+  *	frequency, it means that the match occurred in more than one
+  *	channel.
++ * @NL80211_WOWLAN_TRIG_UNPROTECTED_DEAUTH_DISASSOC: For wakeup reporting only.
++ *	Wake up happened due to unprotected deauth or disassoc frame in MFP.
+  * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers
+  * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number
+  *
+@@ -5662,6 +5816,7 @@ enum nl80211_wowlan_triggers {
+ 	NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS,
+ 	NL80211_WOWLAN_TRIG_NET_DETECT,
+ 	NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS,
++	NL80211_WOWLAN_TRIG_UNPROTECTED_DEAUTH_DISASSOC,
+ 
+ 	/* keep last */
+ 	NUM_NL80211_WOWLAN_TRIG,
+@@ -5817,7 +5972,7 @@ enum nl80211_attr_coalesce_rule {
+ 
+ /**
+  * enum nl80211_coalesce_condition - coalesce rule conditions
+- * @NL80211_COALESCE_CONDITION_MATCH: coalaesce Rx packets when patterns
++ * @NL80211_COALESCE_CONDITION_MATCH: coalesce Rx packets when patterns
+  *	in a rule are matched.
+  * @NL80211_COALESCE_CONDITION_NO_MATCH: coalesce Rx packets when patterns
+  *	in a rule are not matched.
+@@ -5916,7 +6071,7 @@ enum nl80211_if_combination_attrs {
+  * enum nl80211_plink_state - state of a mesh peer link finite state machine
+  *
+  * @NL80211_PLINK_LISTEN: initial state, considered the implicit
+- *	state of non existent mesh peer links
++ *	state of non-existent mesh peer links
+  * @NL80211_PLINK_OPN_SNT: mesh plink open frame has been sent to
+  *	this mesh peer
+  * @NL80211_PLINK_OPN_RCVD: mesh plink open frame has been received
+@@ -5952,7 +6107,7 @@ enum nl80211_plink_state {
+  * @NL80211_PLINK_ACTION_BLOCK: block traffic from this mesh peer
+  * @NUM_NL80211_PLINK_ACTIONS: number of possible actions
+  */
+-enum plink_actions {
++enum nl80211_plink_action {
+ 	NL80211_PLINK_ACTION_NO_ACTION,
+ 	NL80211_PLINK_ACTION_OPEN,
+ 	NL80211_PLINK_ACTION_BLOCK,
+@@ -6209,7 +6364,7 @@ enum nl80211_feature_flags {
+  *	request to use RRM (see %NL80211_ATTR_USE_RRM) with
+  *	%NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests, which will set
+  *	the ASSOC_REQ_USE_RRM flag in the association request even if
+- *	NL80211_FEATURE_QUIET is not advertized.
++ *	NL80211_FEATURE_QUIET is not advertised.
+  * @NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER: This device supports MU-MIMO air
+  *	sniffer which means that it can be configured to hear packets from
+  *	certain groups which can be configured by the
+@@ -6221,13 +6376,15 @@ enum nl80211_feature_flags {
+  *	the BSS that the interface that requested the scan is connected to
+  *	(if available).
+  * @NL80211_EXT_FEATURE_BSS_PARENT_TSF: Per BSS, this driver reports the
+- *	time the last beacon/probe was received. The time is the TSF of the
+- *	BSS that the interface that requested the scan is connected to
+- *	(if available).
++ *	time the last beacon/probe was received. For a non-MLO connection, the
++ *	time is the TSF of the BSS that the interface that requested the scan is
++ *	connected to (if available). For an MLO connection, the time is the TSF
++ *	of the BSS corresponding with link ID specified in the scan request (if
++ *	specified).
+  * @NL80211_EXT_FEATURE_SET_SCAN_DWELL: This driver supports configuration of
+  *	channel dwell time.
+  * @NL80211_EXT_FEATURE_BEACON_RATE_LEGACY: Driver supports beacon rate
+- *	configuration (AP/mesh), supporting a legacy (non HT/VHT) rate.
++ *	configuration (AP/mesh), supporting a legacy (non-HT/VHT) rate.
+  * @NL80211_EXT_FEATURE_BEACON_RATE_HT: Driver supports beacon rate
+  *	configuration (AP/mesh) with HT rates.
+  * @NL80211_EXT_FEATURE_BEACON_RATE_VHT: Driver supports beacon rate
+@@ -6277,6 +6434,7 @@ enum nl80211_feature_flags {
+  *	receiving control port frames over nl80211 instead of the netdevice.
+  * @NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT: This driver/device supports
+  *	(average) ACK signal strength reporting.
++ * @NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT: Backward-compatible ID
+  * @NL80211_EXT_FEATURE_TXQS: Driver supports FQ-CoDel-enabled intermediate
+  *      TXQs.
+  * @NL80211_EXT_FEATURE_SCAN_RANDOM_SN: Driver/device supports randomizing the
+@@ -6301,8 +6459,7 @@ enum nl80211_feature_flags {
+  * @NL80211_EXT_FEATURE_AP_PMKSA_CACHING: Driver/device supports PMKSA caching
+  *	(set/del PMKSA operations) in AP mode.
+  *
+- * @NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD: Driver supports
+- *	filtering of sched scan results using band specific RSSI thresholds.
++ * @NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD: Obsolete
+  *
+  * @NL80211_EXT_FEATURE_STA_TX_PWR: This driver supports controlling tx power
+  *	to a station.
+@@ -6400,6 +6557,22 @@ enum nl80211_feature_flags {
+  *	in authentication and deauthentication frames sent to unassociated peer
+  *	using @NL80211_CMD_FRAME.
+  *
++ * @NL80211_EXT_FEATURE_OWE_OFFLOAD: Driver/Device wants to do OWE DH IE
++ *	handling in station mode.
++ *
++ * @NL80211_EXT_FEATURE_OWE_OFFLOAD_AP: Driver/Device wants to do OWE DH IE
++ *	handling in AP mode.
++ *
++ * @NL80211_EXT_FEATURE_DFS_CONCURRENT: The device supports peer-to-peer or
++ *	ad hoc operation on DFS channels under the control of a concurrent
++ *	DFS master on the same channel as described in FCC-594280 D01
++ *	(Section B.3). This, for example, allows P2P GO and P2P clients to
++ *	operate on DFS channels as long as there's a concurrent BSS connection.
++ *
++ * @NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT: The driver has support for SPP
++ *	(signaling and payload protected) A-MSDUs and this shall be advertised
++ *	in the RSNXE.
++ *
+  * @NUM_NL80211_EXT_FEATURES: number of extended features.
+  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
+  */
+@@ -6441,7 +6614,7 @@ enum nl80211_ext_feature_index {
+ 	NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER,
+ 	NL80211_EXT_FEATURE_AIRTIME_FAIRNESS,
+ 	NL80211_EXT_FEATURE_AP_PMKSA_CACHING,
+-	NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD,
++	NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD, /* obsolete */
+ 	NL80211_EXT_FEATURE_EXT_KEY_ID,
+ 	NL80211_EXT_FEATURE_STA_TX_PWR,
+ 	NL80211_EXT_FEATURE_SAE_OFFLOAD,
+@@ -6471,6 +6644,10 @@ enum nl80211_ext_feature_index {
+ 	NL80211_EXT_FEATURE_PUNCT,
+ 	NL80211_EXT_FEATURE_SECURE_NAN,
+ 	NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA,
++	NL80211_EXT_FEATURE_OWE_OFFLOAD,
++	NL80211_EXT_FEATURE_OWE_OFFLOAD_AP,
++	NL80211_EXT_FEATURE_DFS_CONCURRENT,
++	NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT,
+ 
+ 	/* add new features before the definition below */
+ 	NUM_NL80211_EXT_FEATURES,
+@@ -6555,7 +6732,7 @@ enum nl80211_timeout_reason {
+  *	request parameters IE in the probe request
+  * @NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP: accept broadcast probe responses
+  * @NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE: send probe request frames at
+- *	rate of at least 5.5M. In case non OCE AP is discovered in the channel,
++ *	rate of at least 5.5M. In case non-OCE AP is discovered in the channel,
+  *	only the first probe req in the channel will be sent in high rate.
+  * @NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION: allow probe request
+  *	tx deferral (dot11FILSProbeDelay shall be set to 15ms)
+@@ -6591,7 +6768,7 @@ enum nl80211_timeout_reason {
+  *	received on the 2.4/5 GHz channels to actively scan only the 6GHz
+  *	channels on which APs are expected to be found. Note that when not set,
+  *	the scan logic would scan all 6GHz channels, but since transmission of
+- *	probe requests on non PSC channels is limited, it is highly likely that
++ *	probe requests on non-PSC channels is limited, it is highly likely that
+  *	these channels would passively be scanned. Also note that when the flag
+  *	is set, in addition to the colocated APs, PSC channels would also be
+  *	scanned if the user space has asked for it.
+@@ -6641,6 +6818,8 @@ enum nl80211_acl_policy {
+  * @NL80211_SMPS_STATIC: static SMPS (use a single antenna)
+  * @NL80211_SMPS_DYNAMIC: dynamic smps (start with a single antenna and
+  *	turn on other antennas after CTS/RTS).
++ * @__NL80211_SMPS_AFTER_LAST: internal
++ * @NL80211_SMPS_MAX: highest used enumeration
+  */
+ enum nl80211_smps_mode {
+ 	NL80211_SMPS_OFF,
+@@ -6671,14 +6850,6 @@ enum nl80211_smps_mode {
+  *	applicable for ETSI dfs domain where pre-CAC is valid for ever.
+  * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
+  *	should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
+- * @NL80211_RADAR_BACKGROUND_CHAN_UPDATE: background channel is updated by the
+- *	driver.
+- * @NL80211_RADAR_BACKGROUND_CHAN_EXPAND: background channel is updated by the
+- *	driver and required to expand main operating channel.
+- * @NL80211_RADAR_STA_CAC_SKIPPED: STA set the DFS state to available
+- *	when receiving CSA/assoc resp
+- * @NL80211_RADAR_STA_CAC_EXPIRED: STA set the DFS state to usable
+- *	when STA is disconnected or leaving the channel
+  */
+ enum nl80211_radar_event {
+ 	NL80211_RADAR_DETECTED,
+@@ -6687,10 +6858,6 @@ enum nl80211_radar_event {
+ 	NL80211_RADAR_NOP_FINISHED,
+ 	NL80211_RADAR_PRE_CAC_EXPIRED,
+ 	NL80211_RADAR_CAC_STARTED,
+-	NL80211_RADAR_BACKGROUND_CHAN_UPDATE,
+-	NL80211_RADAR_BACKGROUND_CHAN_EXPAND,
+-	NL80211_RADAR_STA_CAC_SKIPPED,
+-	NL80211_RADAR_STA_CAC_EXPIRED,
+ };
+ 
+ /**
+@@ -6874,6 +7041,8 @@ enum nl80211_bss_select_attr {
+  * @NL80211_NAN_FUNC_PUBLISH: function is publish
+  * @NL80211_NAN_FUNC_SUBSCRIBE: function is subscribe
+  * @NL80211_NAN_FUNC_FOLLOW_UP: function is follow-up
++ * @__NL80211_NAN_FUNC_TYPE_AFTER_LAST: internal use
++ * @NL80211_NAN_FUNC_MAX_TYPE: internal use
+  */
+ enum nl80211_nan_function_type {
+ 	NL80211_NAN_FUNC_PUBLISH,
+@@ -6935,7 +7104,7 @@ enum nl80211_nan_func_term_reason {
+  *	The instance ID for the follow up Service Discovery Frame. This is u8.
+  * @NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID: relevant if the function's type
+  *	is follow up. This is a u8.
+- *	The requestor instance ID for the follow up Service Discovery Frame.
++ *	The requester instance ID for the follow up Service Discovery Frame.
+  * @NL80211_NAN_FUNC_FOLLOW_UP_DEST: the MAC address of the recipient of the
+  *	follow up Service Discovery Frame. This is a binary attribute.
+  * @NL80211_NAN_FUNC_CLOSE_RANGE: is this function limited for devices in a
+@@ -7034,7 +7203,7 @@ enum nl80211_nan_match_attributes {
+ };
+ 
+ /**
+- * nl80211_external_auth_action - Action to perform with external
++ * enum nl80211_external_auth_action - Action to perform with external
+  *     authentication request. Used by NL80211_ATTR_EXTERNAL_AUTH_ACTION.
+  * @NL80211_EXTERNAL_AUTH_START: Start the authentication.
+  * @NL80211_EXTERNAL_AUTH_ABORT: Abort the ongoing authentication.
+@@ -7052,7 +7221,7 @@ enum nl80211_external_auth_action {
+  * @NL80211_FTM_RESP_ATTR_LCI: The content of Measurement Report Element
+  *	(9.4.2.22 in 802.11-2016) with type 8 - LCI (9.4.2.22.10),
+  *	i.e. starting with the measurement token
+- * @NL80211_FTM_RESP_ATTR_CIVIC: The content of Measurement Report Element
++ * @NL80211_FTM_RESP_ATTR_CIVICLOC: The content of Measurement Report Element
+  *	(9.4.2.22 in 802.11-2016) with type 11 - Civic (Section 9.4.2.22.13),
+  *	i.e. starting with the measurement token
+  * @__NL80211_FTM_RESP_ATTR_LAST: Internal
+@@ -7325,7 +7494,7 @@ enum nl80211_peer_measurement_attrs {
+  * @NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED: flag attribute indicating if
+  *	trigger based ranging measurement is supported
+  * @NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED: flag attribute indicating
+- *	if non trigger based ranging measurement is supported
++ *	if non-trigger-based ranging measurement is supported
+  *
+  * @NUM_NL80211_PMSR_FTM_CAPA_ATTR: internal
+  * @NL80211_PMSR_FTM_CAPA_ATTR_MAX: highest attribute number
+@@ -7379,7 +7548,7 @@ enum nl80211_peer_measurement_ftm_capa {
+  *      if neither %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED nor
+  *	%NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set, EDCA based
+  *	ranging will be used.
+- * @NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED: request non trigger based
++ * @NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED: request non-trigger-based
+  *	ranging measurement (flag)
+  *	This attribute and %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED are
+  *	mutually exclusive.
+@@ -7457,7 +7626,7 @@ enum nl80211_peer_measurement_ftm_failur
+  * @NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS: number of FTM Request frames
+  *	transmitted (u32, optional)
+  * @NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES: number of FTM Request frames
+- *	that were acknowleged (u32, optional)
++ *	that were acknowledged (u32, optional)
+  * @NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME: retry time received from the
+  *	busy peer (u32, seconds)
+  * @NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP: actual number of bursts exponent
+@@ -7618,7 +7787,7 @@ enum nl80211_iftype_akm_attributes {
+  * @NL80211_FILS_DISCOVERY_ATTR_INT_MIN: Minimum packet interval (u32, TU).
+  *	Allowed range: 0..10000 (TU = Time Unit)
+  * @NL80211_FILS_DISCOVERY_ATTR_INT_MAX: Maximum packet interval (u32, TU).
+- *	Allowed range: 0..10000 (TU = Time Unit)
++ *	Allowed range: 0..10000 (TU = Time Unit). If set to 0, the feature is disabled.
+  * @NL80211_FILS_DISCOVERY_ATTR_TMPL: Template data for FILS discovery action
+  *	frame including the headers.
+  *
+@@ -7631,7 +7800,6 @@ enum nl80211_fils_discovery_attributes {
+ 	NL80211_FILS_DISCOVERY_ATTR_INT_MIN,
+ 	NL80211_FILS_DISCOVERY_ATTR_INT_MAX,
+ 	NL80211_FILS_DISCOVERY_ATTR_TMPL,
+-	NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INTE,
+ 
+ 	/* keep last */
+ 	__NL80211_FILS_DISCOVERY_ATTR_LAST,
+@@ -7652,7 +7820,8 @@ enum nl80211_fils_discovery_attributes {
+  *
+  * @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT: Maximum packet interval (u32, TU).
+  *	Allowed range: 0..20 (TU = Time Unit). IEEE P802.11ax/D6.0
+- *	26.17.2.3.2 (AP behavior for fast passive scanning).
++ *	26.17.2.3.2 (AP behavior for fast passive scanning). If set to 0, the feature is
++ *	disabled.
+  * @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL: Unsolicited broadcast probe response
+  *	frame template (binary).
+  *
+@@ -7695,6 +7864,7 @@ enum nl80211_sae_pwe_mechanism {
+  *
+  * @NL80211_SAR_TYPE_POWER: power limitation specified in 0.25dBm unit
+  *
++ * @NUM_NL80211_SAR_TYPE: internal
+  */
+ enum nl80211_sar_type {
+ 	NL80211_SAR_TYPE_POWER,
+@@ -7708,6 +7878,8 @@ enum nl80211_sar_type {
+ /**
+  * enum nl80211_sar_attrs - Attributes for SAR spec
+  *
++ * @__NL80211_SAR_ATTR_INVALID: Invalid
++ *
+  * @NL80211_SAR_ATTR_TYPE: the SAR type as defined in &enum nl80211_sar_type.
+  *
+  * @NL80211_SAR_ATTR_SPECS: Nested array of SAR power
+@@ -7739,6 +7911,8 @@ enum nl80211_sar_attrs {
+ /**
+  * enum nl80211_sar_specs_attrs - Attributes for SAR power limit specs
+  *
++ * @__NL80211_SAR_ATTR_SPECS_INVALID: Invalid
++ *
+  * @NL80211_SAR_ATTR_SPECS_POWER: Required (s32)value to specify the actual
+  *	power limit value in units of 0.25 dBm if type is
+  *	NL80211_SAR_TYPE_POWER. (i.e., a value of 44 represents 11 dBm).
+@@ -7853,4 +8027,54 @@ enum nl80211_ap_settings_flags {
+ 	NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT	= 1 << 1,
+ };
+ 
++/**
++ * enum nl80211_wiphy_radio_attrs - wiphy radio attributes
++ *
++ * @__NL80211_WIPHY_RADIO_ATTR_INVALID: Invalid
++ *
++ * @NL80211_WIPHY_RADIO_ATTR_INDEX: Index of this radio (u32)
++ * @NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE: Frequency range supported by this
++ *	radio. Attribute may be present multiple times.
++ * @NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION: Supported interface
++ *	combination for this radio. Attribute may be present multiple times
++ *	and contains attributes defined in &enum nl80211_if_combination_attrs.
++ *
++ * @__NL80211_WIPHY_RADIO_ATTR_LAST: Internal
++ * @NL80211_WIPHY_RADIO_ATTR_MAX: Highest attribute
++ */
++enum nl80211_wiphy_radio_attrs {
++	__NL80211_WIPHY_RADIO_ATTR_INVALID,
++
++	NL80211_WIPHY_RADIO_ATTR_INDEX,
++	NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE,
++	NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION,
++
++	/* keep last */
++	__NL80211_WIPHY_RADIO_ATTR_LAST,
++	NL80211_WIPHY_RADIO_ATTR_MAX = __NL80211_WIPHY_RADIO_ATTR_LAST - 1,
++};
++
++/**
++ * enum nl80211_wiphy_radio_freq_range - wiphy radio frequency range
++ *
++ * @__NL80211_WIPHY_RADIO_FREQ_ATTR_INVALID: Invalid
++ *
++ * @NL80211_WIPHY_RADIO_FREQ_ATTR_START: Frequency range start (u32).
++ *	The unit is kHz.
++ * @NL80211_WIPHY_RADIO_FREQ_ATTR_END: Frequency range end (u32).
++ *	The unit is kHz.
++ *
++ * @__NL80211_WIPHY_RADIO_FREQ_ATTR_LAST: Internal
++ * @NL80211_WIPHY_RADIO_FREQ_ATTR_MAX: Highest attribute
++ */
++enum nl80211_wiphy_radio_freq_range {
++	__NL80211_WIPHY_RADIO_FREQ_ATTR_INVALID,
++
++	NL80211_WIPHY_RADIO_FREQ_ATTR_START,
++	NL80211_WIPHY_RADIO_FREQ_ATTR_END,
++
++	__NL80211_WIPHY_RADIO_FREQ_ATTR_LAST,
++	NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = __NL80211_WIPHY_RADIO_FREQ_ATTR_LAST - 1,
++};
++
+ #endif /* __LINUX_NL80211_H */
+--- a/iwinfo_nl80211.c
++++ b/iwinfo_nl80211.c
+@@ -37,6 +37,11 @@
+ 
+ static struct nl80211_state *nls = NULL;
+ 
++struct nl80211_if_data {
++	int mode;
++	int radio_idx;
++};
++
+ static void nl80211_close(void)
+ {
+ 	if (nls)
+@@ -862,7 +867,7 @@ static char * nl80211_phy2ifname(const c
+ 
+ static int nl80211_get_mode_cb(struct nl_msg *msg, void *arg)
+ {
+-	int *mode = arg;
++	struct nl80211_if_data *data = arg;
+ 	struct nlattr **tb = nl80211_parse(msg);
+ 	const int ifmodes[NL80211_IFTYPE_MAX + 1] = {
+ 		IWINFO_OPMODE_UNKNOWN,		/* unspecified */
+@@ -878,37 +883,57 @@ static int nl80211_get_mode_cb(struct nl
+ 	};
+ 
+ 	if (tb[NL80211_ATTR_IFTYPE])
+-		*mode = ifmodes[nla_get_u32(tb[NL80211_ATTR_IFTYPE])];
++		data->mode = ifmodes[nla_get_u32(tb[NL80211_ATTR_IFTYPE])];
++
++	if (tb[NL80211_ATTR_VIF_RADIO_MASK]) {
++		uint32_t mask = nla_get_u32(tb[NL80211_ATTR_VIF_RADIO_MASK]);
++
++		for (int i = 0; mask && i < 32; i++, mask >>= 1)
++			if (mask & 1)
++				data->radio_idx = i;
++	}
+ 
+ 	return NL_SKIP;
+ }
+ 
+ 
+-static int nl80211_get_mode(const char *ifname, int *buf)
++static int nl80211_get_if_data(const char *ifname, struct nl80211_if_data *data)
+ {
+ 	char *res;
+ 
+-	*buf = IWINFO_OPMODE_UNKNOWN;
+-
+ 	res = nl80211_phy2ifname(ifname);
+ 
++	data->mode = IWINFO_OPMODE_UNKNOWN;
++	data->radio_idx = -1;
+ 	nl80211_request(res ? res : ifname, NL80211_CMD_GET_INTERFACE, 0,
+-	                nl80211_get_mode_cb, buf);
++	                nl80211_get_mode_cb, data);
+ 
+-	return (*buf == IWINFO_OPMODE_UNKNOWN) ? -1 : 0;
++	return (data->mode == IWINFO_OPMODE_UNKNOWN) ? -1 : 0;
++}
++
++static int nl80211_get_mode(const char *ifname, int *buf)
++{
++	struct nl80211_if_data data = {};
++	int ret;
++
++	ret = nl80211_get_if_data(ifname, &data);
++	*buf = data.mode;
++
++	return ret;
+ }
+ 
+ static int __nl80211_hostapd_query(const char *ifname, ...)
+ {
++	struct nl80211_if_data data = {};
+ 	va_list ap, ap_cur;
+ 	char *phy, *search, *dest, *key, *val, buf[128];
+-	int len, mode, found = 0, match = 1;
++	int len, found = 0, match = 1;
+ 	FILE *fp;
+ 
+-	if (nl80211_get_mode(ifname, &mode))
++	if (nl80211_get_if_data(ifname, &data))
+ 		return 0;
+ 
+-	if (mode != IWINFO_OPMODE_MASTER && mode != IWINFO_OPMODE_AP_VLAN)
++	if (data.mode != IWINFO_OPMODE_MASTER && data.mode != IWINFO_OPMODE_AP_VLAN)
+ 		return 0;
+ 
+ 	phy = nl80211_ifname2phy(ifname);
+@@ -916,7 +941,10 @@ static int __nl80211_hostapd_query(const
+ 	if (!phy)
+ 		return 0;
+ 
+-	snprintf(buf, sizeof(buf), "/var/run/hostapd-%s.conf", phy);
++	if (data.radio_idx >= 0)
++		snprintf(buf, sizeof(buf), "/var/run/hostapd-%s.%d.conf", phy, data.radio_idx);
++	else
++		snprintf(buf, sizeof(buf), "/var/run/hostapd-%s.conf", phy);
+ 	fp = fopen(buf, "r");
+ 
+ 	if (!fp)
diff --git a/package/network/utils/layerscape/restool/Makefile b/package/network/utils/layerscape/restool/Makefile
new file mode 100644
index 0000000..bca78fb
--- /dev/null
+++ b/package/network/utils/layerscape/restool/Makefile
@@ -0,0 +1,39 @@
+#
+# Copyright 2017 NXP
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=restool
+PKG_VERSION:=21.08
+PKG_RELEASE:=4
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/nxp-qoriq/restool
+PKG_SOURCE_VERSION:=LSDK-21.08
+PKG_MIRROR_HASH:=3c289e6c9adc2c61445473ecd8b1b1a7b6dfd19a66d3c65f3b83b669e4c3e25b
+
+PKG_FLAGS:=nonshared
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/restool
+  SECTION:=net
+  CATEGORY:=Network
+  TITLE:=Layerscape DPAA2 dynamical management tool
+  DEPENDS:=@TARGET_layerscape_armv8_64b
+endef
+
+MAKE_FLAGS += \
+	DESTDIR="$(PKG_BUILD_DIR)"/output/ \
+	install
+
+define Package/restool/install
+	$(INSTALL_DIR) $(1)/usr/bin/
+	$(CP) $(PKG_BUILD_DIR)/output/usr/local/bin/* $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,restool))
diff --git a/package/network/utils/layerscape/restool/patches/remove-manpage.patch b/package/network/utils/layerscape/restool/patches/remove-manpage.patch
new file mode 100644
index 0000000..5cb9e0a
--- /dev/null
+++ b/package/network/utils/layerscape/restool/patches/remove-manpage.patch
@@ -0,0 +1,18 @@
+--- a/Makefile
++++ b/Makefile
+@@ -53,14 +53,13 @@ restool: $(OBJ)
+ %.1: %.md
+ 	pandoc --standalone --to man $^ -o $@
+ 
+-install: restool scripts/ls-main scripts/ls-append-dpl scripts/ls-debug scripts/restool_completion.sh $(MANPAGE)
++install: restool scripts/ls-main scripts/ls-append-dpl scripts/ls-debug scripts/restool_completion.sh
+ 	install -D -m 755 restool $(DESTDIR)$(bindir)/restool
+ 	install -D -m 755 scripts/ls-main $(DESTDIR)$(bindir)/ls-main
+ 	install -D -m 755 scripts/ls-append-dpl $(DESTDIR)$(bindir)/ls-append-dpl
+ 	install -D -m 755 scripts/ls-debug $(DESTDIR)$(bindir)/ls-debug
+ 	$(foreach symlink, $(RESTOOL_SCRIPT_SYMLINKS), sh -c "cd $(DESTDIR)$(bindir) && ln -sf ls-main $(symlink)" ;)
+ 	install -D -m 755 scripts/restool_completion.sh $(DESTDIR)$(bindir_completion)/restool
+-	install -m 0644 -D $(MANPAGE) $(call get_manpage_destination,$(MANPAGE))
+ 
+ clean:
+ 	rm -f $(OBJ) $(MANPAGE) \
diff --git a/package/network/utils/linux-atm/Makefile b/package/network/utils/linux-atm/Makefile
new file mode 100644
index 0000000..c48309d
--- /dev/null
+++ b/package/network/utils/linux-atm/Makefile
@@ -0,0 +1,200 @@
+#
+# 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:=8
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/$(PKG_NAME)
+PKG_HASH:=9645481a2b16476b59220aa2d6bc5bc41043f291326c9b37581018fbd16dd53a
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+PKG_LICENSE:=GPL-2.0+
+PKG_CPE_ID:=cpe:/a:linux-atm:linux-atm
+PKG_FIXUP:=autoreconf
+PKG_FLAGS:=nonshared
+
+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))))
+
+TARGET_CFLAGS += -I$(LINUX_DIR)/user_headers/include
+
+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 $(1)/etc/hotplug.d/atm $(1)/usr/sbin $(1)/lib/netifd
+	$(INSTALL_BIN) ./files/br2684-up $(1)/lib/netifd/br2684-up
+	$(INSTALL_BIN) ./files/br2684ctl $(1)/etc/init.d/
+	$(INSTALL_CONF) ./files/atm.hotplug $(1)/etc/hotplug.d/atm/00-trigger
+	$(INSTALL_BIN) \
+		./files/br2684ctl_wrap \
+		$(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/atm.hotplug b/package/network/utils/linux-atm/files/atm.hotplug
new file mode 100644
index 0000000..68fb96d
--- /dev/null
+++ b/package/network/utils/linux-atm/files/atm.hotplug
@@ -0,0 +1 @@
+ubus call service event '{ "type": "hotplug.atm", "data": { "name": "'"$DEVICENAME"'" } }'
diff --git a/package/network/utils/linux-atm/files/br2684-up b/package/network/utils/linux-atm/files/br2684-up
new file mode 100644
index 0000000..ba1d670
--- /dev/null
+++ b/package/network/utils/linux-atm/files/br2684-up
@@ -0,0 +1,3 @@
+#!/bin/sh
+. /lib/functions/network.sh
+network_ready_device "$1"
diff --git a/package/network/utils/linux-atm/files/br2684ctl b/package/network/utils/linux-atm/files/br2684ctl
new file mode 100755
index 0000000..6513dd3
--- /dev/null
+++ b/package/network/utils/linux-atm/files/br2684ctl
@@ -0,0 +1,84 @@
+#!/bin/sh /etc/rc.common
+
+START=50
+USE_PROCD=1
+
+start_daemon() {
+	local cfg="$1"
+
+	local atmdev disabled
+
+	config_get_bool disabled "$cfg" disabled 0
+	[ "$disabled" -eq 1 ] && return
+
+	config_get atmdev "$cfg" atmdev 0
+
+	local nameprefix
+	config_get nameprefix "$cfg" nameprefix "nas"
+
+	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
+
+	found=
+	for device in /sys/class/atm/*; do
+		[ -d "$device" ] || break
+		[ "$(cat $device/atmindex)" = "$atmdev" ] || continue
+		found=1
+		break
+	done
+
+	[ -n "$found" ] || return
+
+	local circuit="$atmdev.$vpi.$vci"
+
+	procd_open_instance
+	procd_set_param command \
+		/usr/sbin/br2684ctl_wrap "${nameprefix}${unit}" \
+		-n "$nameprefix" -c "$unit" -e "$encaps" -p "$payload" \
+		-a "$circuit" ${qos:+-q "$qos"} ${sendsize:+-s "$sendsize"} \
+		-S /lib/netifd/br2684-up
+	procd_close_instance
+}
+
+service_triggers() {
+	local script=$(readlink "$initscript")
+	local name=$(basename ${script:-$initscript})
+
+	procd_open_trigger
+	procd_add_raw_trigger hotplug.atm 2000 /etc/init.d/$name reload
+	procd_add_config_trigger "config.change" "network" /etc/init.d/$name reload
+	procd_close_trigger
+}
+
+start_service() {
+	config_load network
+	config_foreach start_daemon atm-bridge
+}
diff --git a/package/network/utils/linux-atm/files/br2684ctl_wrap b/package/network/utils/linux-atm/files/br2684ctl_wrap
new file mode 100644
index 0000000..d1bc98e
--- /dev/null
+++ b/package/network/utils/linux-atm/files/br2684ctl_wrap
@@ -0,0 +1,5 @@
+#!/bin/sh
+. /lib/functions/network.sh
+device="$1"; shift
+network_defer_device "$device"
+exec /usr/sbin/br2684ctl "$@"
diff --git a/package/network/utils/linux-atm/patches/000-debian_2.5.1-5.1.patch b/package/network/utils/linux-atm/patches/000-debian_2.5.1-5.1.patch
new file mode 100644
index 0000000..27bf6b1
--- /dev/null
+++ b/package/network/utils/linux-atm/patches/000-debian_2.5.1-5.1.patch
@@ -0,0 +1,319 @@
+--- 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
+--- 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 */    
+@@ -663,7 +664,7 @@ int no_check = 0;
+     exit(0);
+ 
+   usage:
+-    fprintf(stderr, Usage);
++    fprintf(stderr, "%s", Usage);
+     exit(1);
+ }
+ 
+--- a/src/arpd/arp.c
++++ b/src/arpd/arp.c
+@@ -17,6 +17,7 @@
+ #include <netinet/in.h> /* for ntohs, etc. */
+ #define _LINUX_NETDEVICE_H /* very crude hack for glibc2 */
+ #include <linux/types.h>
++#include <linux/if.h>
+ #include <linux/if_arp.h>
+ #include <linux/if_ether.h>
+ #include <atm.h>
+--- a/src/arpd/itf.c
++++ b/src/arpd/itf.c
+@@ -14,6 +14,7 @@
+ #include <sys/socket.h>
+ #define _LINUX_NETDEVICE_H /* glibc2 */
+ #include <linux/types.h>
++#include <linux/if.h>
+ #include <linux/if_arp.h>
+ 
+ #include "atmd.h"
+--- a/src/maint/atmdump.c
++++ b/src/maint/atmdump.c
+@@ -14,6 +14,7 @@
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <sys/socket.h>
++#include <linux/sockios.h>
+ #include <netinet/in.h> /* for htonl and ntohl */
+ #include <atm.h>
+ 
+--- a/src/maint/saaldump.c
++++ b/src/maint/saaldump.c
+@@ -15,6 +15,7 @@
+ #include <sys/time.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
++#include <linux/sockios.h>
+ #include <atm.h>
+ 
+ #include "pdu.h"
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..41425ee
--- /dev/null
+++ b/package/network/utils/linux-atm/patches/400-portability_fixes.patch
@@ -0,0 +1,70 @@
+--- a/src/ilmid/io.c
++++ b/src/ilmid/io.c
+@@ -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 */
+--- a/src/mpoad/io.c
++++ b/src/mpoad/io.c
+@@ -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>
+--- a/src/sigd/atmsigd.c
++++ b/src/sigd/atmsigd.c
+@@ -283,12 +283,11 @@ static void setup_signals(void)
+ /* ------------------------------- main ...  ------------------------------- */
+ 
+ 
+-static void trace_on_exit(int status,void *dummy)
++static void trace_on_exit(void)
+ {
+     char path[PATH_MAX+1];
+     FILE *file;
+ 
+-    if (!status) return;
+     if (!dump_dir) file = stderr;
+     else {
+ 	sprintf(path,"atmsigd.%d.trace.exit",getpid());
+@@ -517,7 +516,7 @@ int main(int argc,char **argv)
+ 	    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);
+--- a/src/test/align.c
++++ b/src/test/align.c
+@@ -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/linux-atm/patches/500-br2684ctl_script.patch b/package/network/utils/linux-atm/patches/500-br2684ctl_script.patch
new file mode 100644
index 0000000..78aabf8
--- /dev/null
+++ b/package/network/utils/linux-atm/patches/500-br2684ctl_script.patch
@@ -0,0 +1,63 @@
+--- a/src/br2684/br2684ctl.c
++++ b/src/br2684/br2684ctl.c
+@@ -1,3 +1,4 @@
++#define _GNU_SOURCE
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+@@ -43,6 +44,7 @@ struct br2684_params {
+ 
+ 
+ int lastsock, lastitf;
++static char *up_script;
+ 
+ 
+ void fatal(const char *str, int err)
+@@ -185,6 +187,8 @@ int assign_vcc(char *astr, int encap, in
+ 
+ void start_interface(struct br2684_params* params)
+ {
++  char *cmd;
++
+   if (params->astr==NULL) {
+     syslog(LOG_ERR, "Required ATM parameters not specified.");
+     exit(1);
+@@ -193,13 +197,18 @@ void start_interface(struct br2684_param
+   create_br(params->itfnum, params->payload);
+   assign_vcc(params->astr, params->encap, params->payload, params->sndbuf,
+ 	     params->reqqos);
++  if (up_script) {
++    asprintf(&cmd, "%s nas%d", up_script, lastitf);
++    system(cmd);
++    free(cmd);
++  }
+ }
+ 
+ 
+ void usage(char *s)
+ {
+   printf("usage: %s [-b] [[-c number] [-e 0|1] [-s sndbuf] [-q qos] [-p 0|1] "
+-	 "[-a [itf.]vpi.vci]*]*\n", s);
++	 "[-a [itf.]vpi.vci]*]* [-S script]\n", s);
+   printf("  encapsulations: 0=llc, 1=vcmux\n  payloads: 0=routed, 1=bridged\n");
+   exit(1);
+ }
+@@ -225,7 +234,7 @@ int main (int argc, char **argv)
+ 
+   openlog (LOG_NAME,LOG_OPTION,LOG_FACILITY);
+   if (argc>1)
+-    while ((c = getopt(argc, argv,"q:a:bc:e:s:p:?h")) !=EOF)
++    while ((c = getopt(argc, argv,"q:a:bc:e:s:S:p:?h")) !=EOF)
+       switch (c) {
+       case 'q':
+ 	printf ("optarg : %s",optarg);
+@@ -258,6 +267,9 @@ int main (int argc, char **argv)
+ 	  params.sndbuf=8192;
+ 	}
+ 	break;
++      case 'S':
++	up_script = optarg;
++	break;
+       case 'p':	/* payload type: routed (0) or bridged (1) */
+ #ifdef BR2684_FLAG_ROUTED
+ 	params.payload = atoi(optarg);
diff --git a/package/network/utils/linux-atm/patches/501-br2684ctl_itfname.patch b/package/network/utils/linux-atm/patches/501-br2684ctl_itfname.patch
new file mode 100644
index 0000000..839b395
--- /dev/null
+++ b/package/network/utils/linux-atm/patches/501-br2684ctl_itfname.patch
@@ -0,0 +1,74 @@
+--- a/src/br2684/br2684ctl.c
++++ b/src/br2684/br2684ctl.c
+@@ -45,6 +45,7 @@ struct br2684_params {
+ 
+ int lastsock, lastitf;
+ static char *up_script;
++const char *itfname = "nas";
+ 
+ 
+ void fatal(const char *str, int err)
+@@ -73,7 +74,7 @@ int create_pidfile(int num)
+ 
+   if (num < 0) return -1;
+ 
+-  snprintf(name, 32, "/var/run/br2684ctl-nas%d.pid", num);
++  snprintf(name, 32, "/var/run/br2684ctl-%s%d.pid", itfname, num);
+   pidfile = fopen(name, "w");
+   if (pidfile == NULL) return -1;
+   fprintf(pidfile, "%d", getpid());
+@@ -102,7 +103,7 @@ int create_br(int itfnum, int payload)
+         ni.media |= BR2684_FLAG_ROUTED;
+ #endif
+       ni.mtu = 1500;
+-      sprintf(ni.ifname, "nas%d", itfnum);
++      sprintf(ni.ifname, "%s%d", itfname, itfnum);
+       err=ioctl (lastsock, ATM_NEWBACKENDIF, &ni);
+   
+       if (err == 0)
+@@ -167,7 +168,7 @@ int assign_vcc(char *astr, int encap, in
+     
+     be.backend_num = ATM_BACKEND_BR2684;
+     be.ifspec.method = BR2684_FIND_BYIFNAME;
+-    sprintf(be.ifspec.spec.ifname, "nas%d", lastitf);
++    sprintf(be.ifspec.spec.ifname, "%s%d", itfname, lastitf);
+     be.fcs_in = BR2684_FCSIN_NO;
+     be.fcs_out = BR2684_FCSOUT_NO;
+     be.fcs_auto = 0;
+@@ -198,7 +199,7 @@ void start_interface(struct br2684_param
+   assign_vcc(params->astr, params->encap, params->payload, params->sndbuf,
+ 	     params->reqqos);
+   if (up_script) {
+-    asprintf(&cmd, "%s nas%d", up_script, lastitf);
++    asprintf(&cmd, "%s %s%d", up_script, itfname, lastitf);
+     system(cmd);
+     free(cmd);
+   }
+@@ -207,7 +208,7 @@ void start_interface(struct br2684_param
+ 
+ void usage(char *s)
+ {
+-  printf("usage: %s [-b] [[-c number] [-e 0|1] [-s sndbuf] [-q qos] [-p 0|1] "
++  printf("usage: %s [-b] [-n name] [[-c number] [-e 0|1] [-s sndbuf] [-q qos] [-p 0|1] "
+ 	 "[-a [itf.]vpi.vci]*]* [-S script]\n", s);
+   printf("  encapsulations: 0=llc, 1=vcmux\n  payloads: 0=routed, 1=bridged\n");
+   exit(1);
+@@ -234,7 +235,7 @@ int main (int argc, char **argv)
+ 
+   openlog (LOG_NAME,LOG_OPTION,LOG_FACILITY);
+   if (argc>1)
+-    while ((c = getopt(argc, argv,"q:a:bc:e:s:S:p:?h")) !=EOF)
++    while ((c = getopt(argc, argv,"q:a:bn:c:e:s:S:p:?h")) !=EOF)
+       switch (c) {
+       case 'q':
+ 	printf ("optarg : %s",optarg);
+@@ -247,6 +248,9 @@ int main (int argc, char **argv)
+       case 'b':
+ 	background=1;
+ 	break;
++      case 'n':
++	itfname = optarg;
++	break;
+       case 'c':
+ 	/* temporary, to make it work with multiple interfaces: */
+ 	if (params.itfnum>=0) start_interface(&params);
diff --git a/package/network/utils/linux-atm/patches/510-remove-LINUX_NETDEVICE-hack.patch b/package/network/utils/linux-atm/patches/510-remove-LINUX_NETDEVICE-hack.patch
new file mode 100644
index 0000000..c16df18
--- /dev/null
+++ b/package/network/utils/linux-atm/patches/510-remove-LINUX_NETDEVICE-hack.patch
@@ -0,0 +1,52 @@
+This fixes the following compile problem with kernel 4.20:
+
+In file included from arp.c:20:0:
+include/linux/if_arp.h:121:16: error: 'IFNAMSIZ' undeclared here (not in a function)
+  char  arp_dev[IFNAMSIZ];
+                ^~~~~~~~
+make[7]: *** [Makefile:459: arp.o] Error 1
+
+This is caused by commit 6a12709da354 ("net: if_arp: use define instead 
+of hard-coded value") in the upstream Linux kernel which is integrated 
+in Linux 4.20.
+
+--- a/src/oamd/io.c
++++ b/src/oamd/io.c
+@@ -20,7 +20,6 @@
+ #include <net/if.h>
+ #include <netinet/in.h>
+ #include <atm.h>
+-#define _LINUX_NETDEVICE_H	/* glibc2 */
+ #include <linux/types.h>
+ #include <linux/if_arp.h>
+ 
+--- a/src/arpd/itf.c
++++ b/src/arpd/itf.c
+@@ -12,7 +12,6 @@
+ #include <sys/types.h>
+ #include <linux/atmclip.h>
+ #include <sys/socket.h>
+-#define _LINUX_NETDEVICE_H /* glibc2 */
+ #include <linux/types.h>
+ #include <linux/if.h>
+ #include <linux/if_arp.h>
+--- a/src/arpd/io.c
++++ b/src/arpd/io.c
+@@ -21,7 +21,6 @@
+ #include <atm.h>
+ #include <linux/atmclip.h> /* for CLIP_DEFAULT_IDLETIMER */
+ #include <linux/atmarp.h>
+-#define _LINUX_NETDEVICE_H /* glibc2 */
+ #include <linux/types.h>
+ #include <linux/if_arp.h>
+ 
+--- a/src/arpd/arp.c
++++ b/src/arpd/arp.c
+@@ -15,7 +15,6 @@
+ #include <sys/types.h>
+ #include <sys/socket.h> /* for linux/if_arp.h */
+ #include <netinet/in.h> /* for ntohs, etc. */
+-#define _LINUX_NETDEVICE_H /* very crude hack for glibc2 */
+ #include <linux/types.h>
+ #include <linux/if.h>
+ #include <linux/if_arp.h>
diff --git a/package/network/utils/linux-atm/patches/600-musl-include.patch b/package/network/utils/linux-atm/patches/600-musl-include.patch
new file mode 100644
index 0000000..2b2268d
--- /dev/null
+++ b/package/network/utils/linux-atm/patches/600-musl-include.patch
@@ -0,0 +1,30 @@
+--- a/src/include/atmd.h
++++ b/src/include/atmd.h
+@@ -10,6 +10,7 @@
+ 
+ #include <stdint.h>
+ #include <stdio.h>
++#include <string.h>
+ #include <sys/types.h>
+ #include <sys/time.h>
+ 
+--- a/src/lib/unix.c
++++ b/src/lib/unix.c
+@@ -8,6 +8,7 @@
+ 
+ #include <stdlib.h>
+ #include <stdio.h>
++#include <string.h>
+ #include <unistd.h>
+ #include <errno.h>
+ #include <sys/types.h>
+--- a/src/sigd/kernel.c
++++ b/src/sigd/kernel.c
+@@ -8,6 +8,7 @@
+ 
+ #include <stdlib.h>
+ #include <stdio.h>
++#include <string.h>
+ #include <errno.h>
+ #include <assert.h>
+ 
diff --git a/package/network/utils/linux-atm/patches/700-fix-gcc14-build.patch b/package/network/utils/linux-atm/patches/700-fix-gcc14-build.patch
new file mode 100644
index 0000000..a19dc6c
--- /dev/null
+++ b/package/network/utils/linux-atm/patches/700-fix-gcc14-build.patch
@@ -0,0 +1,82 @@
+--- a/src/arpd/io.c
++++ b/src/arpd/io.c
+@@ -615,7 +615,7 @@ int ip_itf_info(int number,uint32_t *ip,
+ int get_local(int fd,struct sockaddr_atmsvc *addr)
+ {
+     int result;
+-    size_t length;
++    socklen_t length;
+ 
+     length = sizeof(struct sockaddr_atmsvc);
+     result = getsockname(fd,(struct sockaddr *) addr,&length);
+--- a/src/led/conn.c
++++ b/src/led/conn.c
+@@ -405,7 +405,7 @@ Conn_t *accept_conn(Conn_t *conn)
+ {
+         Conn_t *new;
+         struct sockaddr_atmsvc addr;
+-        size_t len;
++        socklen_t len;
+         int fd;
+         char buff[MAX_ATM_ADDR_LEN+1];
+ 
+@@ -538,7 +538,7 @@ static int handle_accept(Conn_t *conn)
+  */
+ static int handle_data(Conn_t *conn)
+ {
+-        char buff[MAX_CTRL_FRAME];
++        unsigned char buff[MAX_CTRL_FRAME];
+         int retval;
+ 
+         retval = recv_frame(conn, buff, sizeof(buff));
+--- a/src/led/frames.c
++++ b/src/led/frames.c
+@@ -312,7 +312,7 @@ static void handle_ready_ind(Conn_t *con
+  * dependant handler functions.
+  * Returns < 0 for serious error
+  */
+-int handle_frame(Conn_t *conn, char *buff, int size)
++int handle_frame(Conn_t *conn, unsigned char *buff, int size)
+ {
+         struct ctrl_frame *frame;
+ 
+--- a/src/led/frames.h
++++ b/src/led/frames.h
+@@ -13,7 +13,7 @@ int validate_frame(unsigned char *buff,
+ void send_ready_ind(Conn_t *conn);
+ void send_register_req(void);
+ 
+-int handle_frame(Conn_t *conn, char *buff, int size);
++int handle_frame(Conn_t *conn, unsigned char *buff, int size);
+ uint32_t send_flush_req(Conn_t *conn);
+ 
+ void parse_tlvs(uint16_t opcode, unsigned char *tlvp, int numtlvs, int sizeoftlvs);
+--- a/src/led/join.c
++++ b/src/led/join.c
+@@ -43,7 +43,7 @@ static int read_join_rsp(char *buff, int
+ static int parse_join_rsp(unsigned char *buff, int size);
+ 
+ static int get_bus_addr(struct sockaddr_atmsvc *addr);
+-static int read_bus_arp(Conn_t *conn, struct sockaddr_atmsvc *addr, char *buff, int buffsize);
++static int read_bus_arp(Conn_t *conn, struct sockaddr_atmsvc *addr, unsigned char *buff, int buffsize);
+ 
+ /*
+  * 5.1, Initial state
+@@ -693,7 +693,7 @@ static int get_bus_addr(struct sockaddr_
+         fd_set rfds;
+         struct timeval tv;
+         int n = 0, retval, timeout;
+-        char buff[MAX_CTRL_FRAME];
++        unsigned char buff[MAX_CTRL_FRAME];
+ 
+         timeout = 4; /* wait response for 4 seconds */
+         lec_params.c7c_current_timeout = 1;
+@@ -740,7 +740,7 @@ static int get_bus_addr(struct sockaddr_
+  * Tries to read BUS ATM address in *addr
+  * returns < 0 for error, 0 for not found > 0 for success
+  */
+-static int read_bus_arp(Conn_t *conn, struct sockaddr_atmsvc *addr, char *buff, int buffsize)
++static int read_bus_arp(Conn_t *conn, struct sockaddr_atmsvc *addr, unsigned char *buff, int buffsize)
+ {
+         int frame_size;
+         struct ctrl_frame *frame;
diff --git a/package/network/utils/ltq-dsl-base/Makefile b/package/network/utils/ltq-dsl-base/Makefile
new file mode 100644
index 0000000..b51851f
--- /dev/null
+++ b/package/network/utils/ltq-dsl-base/Makefile
@@ -0,0 +1,34 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ltq-dsl-base
+PKG_RELEASE:=3
+
+PKG_FLAGS:=nonshared
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ltq-dsl-base
+  SECTION:=net
+  CATEGORY:=Network
+  TITLE:=DSL related files for Intel/Lantiq DSL Chipsets
+  URL:=http://openwrt.org/
+  DEPENDS:=@(TARGET_lantiq||TARGET_ipq40xx) +jshn
+endef
+
+define Package/ltq-dsl-base/description
+  This package contains DSL related files for Intel/Lantiq DSL Chipsets.
+endef
+
+define Build/Compile
+endef
+
+define Package/ltq-dsl-base/install
+	$(CP) ./files/* $(1)/
+endef
+
+$(eval $(call BuildPackage,ltq-dsl-base))
diff --git a/package/network/utils/ltq-dsl-base/files/etc/hotplug.d/dsl/led_dsl.sh b/package/network/utils/ltq-dsl-base/files/etc/hotplug.d/dsl/led_dsl.sh
new file mode 100755
index 0000000..dd8e84a
--- /dev/null
+++ b/package/network/utils/ltq-dsl-base/files/etc/hotplug.d/dsl/led_dsl.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+[ "$DSL_NOTIFICATION_TYPE" = "DSL_INTERFACE_STATUS" ] || exit 0
+
+. /lib/functions.sh
+. /lib/functions/leds.sh
+
+led_dsl_up() {
+	case "$(config_get led_dsl trigger)" in
+	"netdev")
+		led_set_attr $1 "trigger" "netdev"
+		led_set_attr $1 "device_name" "$(config_get led_dsl dev)"
+		for m in $(config_get led_dsl mode); do
+			led_set_attr $1 "$m" "1"
+		done
+		;;
+	*)
+		led_on $1
+		;;
+	esac
+}
+
+config_load system
+config_get led led_dsl sysfs
+if [ -n "$led" ]; then
+	case "$DSL_INTERFACE_STATUS" in
+	  "HANDSHAKE")  led_timer $led 500 500;;
+	  "TRAINING")   led_timer $led 200 200;;
+	  "UP")		led_dsl_up $led;;
+	  *)		led_off $led
+	esac
+fi
diff --git a/package/network/utils/ltq-dsl-base/files/etc/hotplug.d/dsl/pppoa.sh b/package/network/utils/ltq-dsl-base/files/etc/hotplug.d/dsl/pppoa.sh
new file mode 100755
index 0000000..4506737
--- /dev/null
+++ b/package/network/utils/ltq-dsl-base/files/etc/hotplug.d/dsl/pppoa.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+[ "$DSL_NOTIFICATION_TYPE" = "DSL_INTERFACE_STATUS" ] || exit 0
+
+. /usr/share/libubox/jshn.sh
+. /lib/functions.sh
+
+include /lib/network
+scan_interfaces
+
+interfaces=$(ubus list network.interface.\* | cut -d"." -f3)
+for ifc in $interfaces; do
+
+	json_load "$(ifstatus $ifc)"
+
+	json_get_var proto proto
+	if [ "$proto" != "pppoa" ]; then
+		continue
+	fi
+
+	json_get_var up up
+	config_get_bool auto "$ifc" auto 1
+	if [ "$DSL_INTERFACE_STATUS" = "UP" ]; then
+		if [ "$up" != 1 ] && [ "$auto" = 1 ]; then
+			( sleep 1; ifup "$ifc" ) &
+		fi
+	else
+		if [ "$up" = 1 ] && [ "$auto" = 1 ]; then
+			( sleep 1; ifdown "$ifc" ) &
+		else
+			json_get_var autostart autostart
+			if [ "$up" != 1 ] && [ "$autostart" = 1 ]; then
+				( sleep 1; ifdown "$ifc" ) &
+			fi
+		fi
+	fi
+done
diff --git a/package/network/utils/ltq-dsl-base/files/sbin/dsl_notify.sh b/package/network/utils/ltq-dsl-base/files/sbin/dsl_notify.sh
new file mode 100755
index 0000000..d615db5
--- /dev/null
+++ b/package/network/utils/ltq-dsl-base/files/sbin/dsl_notify.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+#
+# This script is called by dsl_cpe_control whenever there is a DSL event
+# and calls any available hotplug script(s) in /etc/hotplug.d/dsl.
+
+exec /sbin/hotplug-call dsl
diff --git a/package/network/utils/net-snmp/Makefile b/package/network/utils/net-snmp/Makefile
new file mode 100644
index 0000000..75a80cc
--- /dev/null
+++ b/package/network/utils/net-snmp/Makefile
@@ -0,0 +1,292 @@
+#
+# Copyright (C) 2006-2017 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:=net-snmp
+PKG_VERSION:=5.8
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/net-snmp
+PKG_HASH:=b2fc3500840ebe532734c4786b0da4ef0a5f67e51ef4c86b3345d697e4976adf
+PKG_MAINTAINER:=Stijn Tintel <stijn@linux-ipv6.be>
+PKG_LICENSE:=MIT BSD-3-Clause-Clear
+PKG_CPE_ID:=cpe:/a:net-snmp:net-snmp
+
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/net-snmp/Default
+  SECTION:=net
+  CATEGORY:=Network
+  URL:=http://www.net-snmp.org/
+endef
+
+define Package/net-snmp/Default/description
+ Simple Network Management Protocol (SNMP) is a widely used protocol for
+ monitoring the health and welfare of network equipment (eg. routers),
+ computer equipment and even devices like UPSs. Net-SNMP is a suite of
+ applications used to implement SNMP v1, SNMP v2c and SNMP v3 using both
+ IPv4 and IPv6.
+endef
+
+
+define Package/libnetsnmp
+$(call Package/net-snmp/Default)
+  SECTION:=libs
+  CATEGORY:=Libraries
+  DEPENDS:=+libnl-tiny +libpci
+  TITLE:=Open source SNMP implementation (libraries)
+endef
+
+define Package/libnetsnmp/description
+$(call Package/net-snmp/Default/description)
+ .
+ This package contains shared libraries, needed by other programs.
+endef
+
+
+define Package/snmp-mibs
+$(call Package/net-snmp/Default)
+  TITLE:=Open source SNMP implementation (MIB-files)
+endef
+
+define Package/snmp-mibs/description
+$(call Package/net-snmp/Default/description)
+ .
+ This package contains SNMP MIB-Files.
+endef
+
+
+define Package/snmp-utils
+$(call Package/net-snmp/Default)
+  DEPENDS:=+libnetsnmp
+  TITLE:=Open source SNMP implementation (utilities)
+endef
+
+define Package/snmp-utils/description
+$(call Package/net-snmp/Default/description)
+ .
+ This package contains SNMP client utilities:
+   - snmpget
+   - snmpset
+   - snmpstatus
+   - snmptest
+   - snmptrap
+   - snmpwalk
+endef
+
+
+define Package/snmpd
+$(call Package/net-snmp/Default)
+  DEPENDS:=+libnetsnmp
+  TITLE:=Open source SNMP implementation (daemon)
+endef
+
+define Package/snmpd/description
+$(call Package/net-snmp/Default/description)
+ .
+ This package contains the SNMP agent, dynamically linked.
+endef
+
+
+define Package/snmpd-static
+$(call Package/net-snmp/Default)
+  DEPENDS:=+snmpd
+  TITLE:=Open source SNMP implementation (daemon)
+  BUILDONLY:=1
+endef
+
+
+define Package/snmptrapd
+$(call Package/net-snmp/Default)
+  DEPENDS:=+libnetsnmp
+  TITLE:=Open source SNMP implementation (notification receiver)
+endef
+
+define Package/snmptrapd/description
+$(call Package/net-snmp/Default/description)
+ .
+ This package contains the SNMP notification receiver.
+endef
+
+
+SNMP_MIB_MODULES_INCLUDED = \
+	agent/extend \
+	agentx \
+	host/hr_device \
+	host/hr_disk \
+	host/hr_filesys \
+	host/hr_network \
+	host/hr_partition \
+	host/hr_proc \
+	host/hr_storage \
+	host/hr_system \
+	ieee802dot11 \
+	if-mib/ifXTable \
+	ip-mib/inetNetToMediaTable \
+	mibII/at \
+	mibII/icmp \
+	mibII/ifTable \
+	mibII/ip \
+	mibII/snmp_mib \
+	mibII/sysORTable \
+	mibII/system_mib \
+	mibII/tcp \
+	mibII/udp \
+	mibII/vacm_context \
+	mibII/vacm_vars \
+	snmpv3/snmpEngine \
+	snmpv3/snmpMPDStats \
+	snmpv3/usmConf \
+	snmpv3/usmStats \
+	snmpv3/usmUser \
+	tunnel \
+	ucd-snmp/disk \
+	ucd-snmp/dlmod \
+	ucd-snmp/extensible \
+	ucd-snmp/loadave \
+	ucd-snmp/memory \
+	ucd-snmp/pass \
+	ucd-snmp/pass_persist \
+	ucd-snmp/proc \
+	ucd-snmp/vmstat \
+	util_funcs \
+	utilities/execute \
+
+SNMP_MIB_MODULES_EXCLUDED = \
+	agent_mibs \
+	disman/event \
+	disman/schedule \
+	hardware \
+	host \
+	if-mib \
+	ip-mib \
+	mibII \
+	notification \
+	notification-log-mib \
+	snmpv3mibs \
+	target \
+	tcp-mib \
+	ucd_snmp \
+	udp-mib \
+	utilities \
+
+SNMP_TRANSPORTS_INCLUDED = Callback UDP Unix
+
+SNMP_TRANSPORTS_EXCLUDED = TCP TCPIPv6
+
+TARGET_CFLAGS += $(FPIC)
+TARGET_CPPFLAGS += -I$(STAGING_DIR)/usr/include/libnl-tiny
+
+CONFIGURE_ARGS += \
+	--enable-mfd-rewrites \
+	--enable-shared \
+	--enable-static \
+	--with-endianness=$(if $(CONFIG_BIG_ENDIAN),big,little) \
+	--with-logfile=/var/log/snmpd.log \
+	--with-persistent-directory=/usr/lib/snmp/ \
+	--with-default-snmp-version=1 \
+	--with-sys-contact=root@localhost \
+	--with-sys-location=Unknown \
+	--enable-applications \
+	--disable-debugging \
+	--disable-manuals \
+	--disable-scripts \
+	--with-out-mib-modules="$(SNMP_MIB_MODULES_EXCLUDED)" \
+	--with-mib-modules="$(SNMP_MIB_MODULES_INCLUDED)" \
+	--with-out-transports="$(SNMP_TRANSPORTS_EXCLUDED)" \
+	--with-transports="$(SNMP_TRANSPORTS_INCLUDED)" \
+	--without-openssl \
+	--without-libwrap \
+	--without-mysql \
+	--without-rpm \
+	--without-zlib \
+	--with-nl \
+	 $(call autoconf_bool,CONFIG_IPV6,ipv6) \
+	--disable-perl-cc-checks \
+	--disable-embedded-perl \
+	--without-perl-modules
+
+CONFIGURE_VARS += \
+	ac_cv_header_netlink_netlink_h=yes \
+	ac_cv_header_pcre_h=no \
+	netsnmp_cv_func_nl_connect_LIBS=-lnl-tiny \
+
+ifeq ($(CONFIG_IPV6),y)
+SNMP_TRANSPORTS_INCLUDED+= UDPIPv6
+endif
+
+TARGET_LDFLAGS += -L$(TOOLCHAIN_DIR)/usr/lib
+
+define Build/Compile
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		INSTALL_PREFIX="$(PKG_INSTALL_DIR)" \
+		LDFLAGS="$(TARGET_LDFLAGS) -lm -lc" \
+		all install
+endef
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(2)/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/net-snmp-config $(2)/bin/
+	$(SED) 's,=/usr,=$(STAGING_DIR)/usr,g' $(2)/bin/net-snmp-config
+	$(INSTALL_DIR) $(STAGING_DIR)/usr/bin
+	$(LN) $(STAGING_DIR)/host/bin/net-snmp-config $(STAGING_DIR)/usr/bin/
+
+	$(INSTALL_DIR) $(1)/usr/include
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/net-snmp $(1)/usr/include/
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libnetsnmp{,agent,helpers,mibs}.{a,so*} $(1)/usr/lib/
+endef
+
+define Package/libnetsnmp/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libnetsnmp{,agent,helpers,mibs}.so.* $(1)/usr/lib/
+endef
+
+define Package/snmp-mibs/install
+	$(INSTALL_DIR) $(1)/usr/share/snmp/mibs
+	$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/snmp/mibs/* $(1)/usr/share/snmp/mibs/
+endef
+
+define Package/snmp-utils/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/snmp{get,set,status,test,trap,walk} $(1)/usr/bin/
+endef
+
+define Package/snmpd/conffiles
+/etc/config/snmpd
+endef
+
+define Package/snmpd/install
+	$(INSTALL_DIR) $(1)/etc/config
+	$(INSTALL_DATA) ./files/snmpd.conf $(1)/etc/config/snmpd
+	$(INSTALL_DIR) $(1)/etc/snmp
+	$(LN) /var/run/snmpd.conf $(1)/etc/snmp/
+	$(INSTALL_DIR) $(1)/etc/init.d
+	$(INSTALL_BIN) ./files/snmpd.init $(1)/etc/init.d/snmpd
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/snmpd $(1)/usr/sbin/snmpd
+endef
+
+define Package/snmptrapd/install
+	$(INSTALL_DIR) $(1)/etc/init.d
+	$(INSTALL_BIN) ./files/snmptrapd.init $(1)/etc/init.d/snmptrapd
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libnetsnmptrapd.so.* $(1)/usr/lib/
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/snmptrapd $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,libnetsnmp))
+$(eval $(call BuildPackage,snmp-mibs))
+$(eval $(call BuildPackage,snmp-utils))
+$(eval $(call BuildPackage,snmpd))
+$(eval $(call BuildPackage,snmpd-static))
+$(eval $(call BuildPackage,snmptrapd))
diff --git a/package/network/utils/net-snmp/files/snmpd.conf b/package/network/utils/net-snmp/files/snmpd.conf
new file mode 100644
index 0000000..e18864d
--- /dev/null
+++ b/package/network/utils/net-snmp/files/snmpd.conf
@@ -0,0 +1,130 @@
+config agent
+	option agentaddress UDP:161,UDP6:161
+
+config agentx
+	option agentxsocket /var/run/agentx.sock
+
+config com2sec public
+	option secname ro
+	option source default
+	option community public
+
+config com2sec private
+	option secname rw
+	option source localhost
+	option community private
+
+config com2sec6 public6
+	option secname ro
+	option source default
+	option community public
+
+config com2sec6 private6
+	option secname rw
+	option source localhost
+	option community private
+
+config group public_v1
+	option group public
+	option version v1
+	option secname ro
+
+config group public_v2c
+	option group public
+	option version v2c
+	option secname ro
+
+config group public_usm
+	option group public
+	option version usm
+	option secname ro
+
+config group private_v1
+	option group private
+	option version v1
+	option secname rw
+
+config group private_v2c
+	option group private
+	option version v2c
+	option secname rw
+
+config group private_usm
+	option group private
+	option version usm
+	option secname rw
+
+config view all
+	option viewname all
+	option type included
+	option oid .1
+
+config access public_access
+	option group public
+	option context none
+	option version any
+	option level noauth
+	option prefix exact
+	option read all
+	option write none
+	option notify none
+
+config access private_access
+	option group private
+	option context none
+	option version any
+	option level noauth
+	option prefix exact
+	option read all
+	option write all
+	option notify all
+
+config system
+	option sysLocation	'office'
+	option sysContact	'bofh@example.com'
+	option sysName		'HeartOfGold'
+#	option sysServices	72
+#	option sysDescr		'adult playground'
+#	option sysObjectID	'1.2.3.4'
+
+config exec
+	option name	filedescriptors
+	option prog	/bin/cat
+	option args	/proc/sys/fs/file-nr
+#	option miboid	1.2.3.4
+
+config engineid
+#	option engineid 'LEDE'
+	option engineidtype '3'
+	option engineidnic 'eth0'
+
+#config trapcommunity 'trapcommunity'
+#	option community 'public'
+
+#config trapsink
+#	option host 'nms.system.com'
+#	option community 'public'
+#	option port '162'
+
+#config trap2sink
+#	option host 'nms.system.com'
+#	option community 'secret'
+#	option port '162'
+
+#config informsink
+#	option host 'nms.sytem.com'
+#	option community 'public'
+#	option port '162'
+
+#config authtrapenable 'authtrapenable'
+#	option enable '1'
+
+#config v1trapaddress 'v1trapaddress'
+#	option host '1.2.3.4'
+
+#config trapsess 'trapsess'
+#	option trapsess	'-v 3 -e 0x80001f88808c18d3f7b0000 -u trapuser -a MD5 -A administrator -l authPriv -x DES -X rootpasswd udp:127.0.0.1:162'
+
+config snmpd general
+	option enabled '1'
+#	list network 'wan'
diff --git a/package/network/utils/net-snmp/files/snmpd.init b/package/network/utils/net-snmp/files/snmpd.init
new file mode 100644
index 0000000..fbae9c2
--- /dev/null
+++ b/package/network/utils/net-snmp/files/snmpd.init
@@ -0,0 +1,359 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2008 OpenWrt.org
+START=50
+
+USE_PROCD=1
+PROG="/usr/sbin/snmpd"
+
+CONFIGFILE="/var/run/snmpd.conf"
+
+snmpd_agent_add() {
+	local cfg="$1"
+
+	config_get agentaddress "$cfg" agentaddress
+	[ -n "$agentaddress" ] || return 0
+	echo "agentaddress $agentaddress" >> $CONFIGFILE
+}
+
+snmpd_agentx_add() {
+	local cfg="$1"
+	echo "master agentx" >> $CONFIGFILE
+	config_get agentxsocket "$cfg" agentxsocket
+	[ -n "$agentxsocket" ] && echo "agentXSocket $agentxsocket" >> $CONFIGFILE
+}
+
+snmpd_system_add() {
+	local cfg="$1"
+	config_get syslocation "$cfg" sysLocation
+	[ -n "$syslocation" ] && echo "sysLocation $syslocation" >> $CONFIGFILE
+	config_get syscontact "$cfg" sysContact
+	[ -n "$syscontact" ] && echo "sysContact $syscontact" >> $CONFIGFILE
+	config_get sysname "$cfg" sysName
+	[ -n "$sysname" ] && echo "sysName $sysname" >> $CONFIGFILE
+	config_get sysservice "$cfg" sysService
+	[ -n "$sysservice" ] && echo "sysService $sysservice" >> $CONFIGFILE
+	config_get sysdescr "$cfg" sysDescr
+	[ -n "$sysdescr" ] && echo "sysDescr $sysdescr" >> $CONFIGFILE
+	config_get sysobjectid "$cfg" sysObjectID
+	[ -n "$sysobjectid" ] && echo "sysObjectID $sysobjectid" >> $CONFIGFILE
+}
+
+snmpd_com2sec_add() {
+	local cfg="$1"
+	config_get secname "$cfg" secname
+	[ -n "$secname" ] || return 0
+	config_get source "$cfg" source
+	[ -n "$source" ] || return 0
+	config_get community "$cfg" community
+	[ -n "$community" ] || return 0
+	echo "com2sec $secname $source $community" >> $CONFIGFILE
+}
+
+snmpd_com2sec6_add() {
+	local cfg="$1"
+	config_get secname "$cfg" secname
+	[ -n "$secname" ] || return 0
+	config_get source "$cfg" source
+	[ -n "$source" ] || return 0
+	config_get community "$cfg" community
+	[ -n "$community" ] || return 0
+	echo "com2sec6 $secname $source $community" >> $CONFIGFILE
+}
+
+snmpd_group_add() {
+	local cfg="$1"
+	config_get group "$cfg" group
+	[ -n "$group" ] || return 0
+	config_get version "$cfg" version
+	[ -n "$version" ] || return 0
+	config_get secname "$cfg" secname
+	[ -n "$secname" ] || return 0
+	echo "group $group $version $secname" >> $CONFIGFILE
+}
+
+snmpd_view_add() {
+	local cfg="$1"
+	config_get viewname "$cfg" viewname
+	[ -n "$viewname" ] || return 0
+	config_get type "$cfg" type
+	[ -n "$type" ] || return 0
+	config_get oid "$cfg" oid
+	[ -n "$oid" ] || return 0
+	# optional mask
+	config_get mask "$cfg" mask
+	echo "view $viewname $type $oid $mask" >> $CONFIGFILE
+}
+
+snmpd_access_add() {
+	local cfg="$1"
+	config_get group "$cfg" group
+	[ -n "$group" ] || return 0
+	config_get context "$cfg" context
+	[ -n $context ] || return 0
+	[ "$context" == "none" ] && context='""'
+	config_get version "$cfg" version
+	[ -n "$version" ] || return 0
+	config_get level "$cfg" level
+	[ -n "$level" ] || return 0
+	config_get prefix "$cfg" prefix
+	[ -n "$prefix" ] || return 0
+	config_get read "$cfg" read
+	[ -n "$read" ] || return 0
+	config_get write "$cfg" write
+	[ -n "$write" ] || return 0
+	config_get notify "$cfg" notify
+	[ -n "$notify" ] || return 0
+	echo "access $group $context $version $level $prefix $read $write $notify" >> $CONFIGFILE
+}
+
+snmpd_trap_hostname_add() {
+	local cfg="$1"
+	config_get hostname "$cfg" HostName
+	config_get port "$cfg" Port
+	config_get community "$cfg" Community
+	config_get type "$cfg" Type
+	echo "$type $hostname $community $port" >> $CONFIGFILE
+}
+
+snmpd_trap_ip_add() {
+	local cfg="$1"
+	config_get host_ip "$cfg" HostIP
+	config_get port "$cfg" Port
+	config_get community "$cfg" Community
+	config_get type "$cfg" Type
+	echo "$type $host_ip $community $port" >> $CONFIGFILE
+}
+
+snmpd_access_default_add() {
+	local cfg="$1"
+	config_get mode "$cfg" Mode
+	config_get community "$cfg" CommunityName
+	config_get oidrestrict "$cfg" RestrictOID
+	config_get oid "$cfg" RestrictedOID
+	echo -n "$mode $community default" >> $CONFIGFILE
+	[ "$oidrestrict" == "yes" ] && echo " $oid" >> $CONFIGFILE
+	[ "$oidrestrict" == "no" ] && echo "" >> $CONFIGFILE
+}
+
+snmpd_access_HostName_add() {
+	local cfg="$1"
+	config_get hostname "$cfg" HostName
+	config_get mode "$cfg" Mode
+	config_get community "$cfg" CommunityName
+	config_get oidrestrict "$cfg" RestrictOID
+	config_get oid "$cfg" RestrictedOID
+	echo -n "$mode $community $hostname" >> $CONFIGFILE
+	[ "$oidrestrict" == "yes" ] && echo " $oid" >> $CONFIGFILE
+	[ "$oidrestrict" == "no" ] && echo "" >> $CONFIGFILE
+}
+
+snmpd_access_HostIP_add() {
+	local cfg="$1"
+	config_get host_ip "$cfg" HostIP
+	config_get ip_mask "$cfg" IPMask
+	config_get mode "$cfg" Mode
+	config_get community "$cfg" CommunityName
+	config_get oidrestrict "$cfg" RestrictOID
+	config_get oid "$cfg" RestrictedOID
+	echo -n "$mode $community $host_ip/$ip_mask" >> $CONFIGFILE
+	[ "$oidrestrict" == "yes" ] && echo " $oid" >> $CONFIGFILE
+	[ "$oidrestrict" == "no" ] && echo "" >> $CONFIGFILE
+}
+
+snmpd_pass_add() {
+	local cfg="$1"
+	local pass='pass'
+
+	config_get miboid "$cfg" miboid
+	[ -n "$miboid" ] || return 0
+	config_get prog "$cfg" prog
+	[ -n "$prog" ] || return 0
+	config_get_bool persist "$cfg" persist 0
+	[ $persist -ne 0 ] && pass='pass_persist'
+	config_get priority "$cfg" priority
+	priority=${priority:+-p $priority}
+	echo "$pass $priority $miboid $prog" >> $CONFIGFILE
+}
+
+snmpd_exec_add() {
+	local cfg="$1"
+
+	config_get name "$cfg" name
+	[ -n "$name" ] || return 0
+	config_get prog "$cfg" prog
+	[ -n "$prog" ] || return 0
+	config_get args "$cfg" args
+	config_get miboid "$cfg" miboid
+	echo "exec $miboid $name $prog $args" >> $CONFIGFILE
+}
+
+snmpd_extend_add() {
+	local cfg="$1"
+
+	config_get name "$cfg" name
+	[ -n "$name" ] || return 0
+	config_get prog "$cfg" prog
+	[ -n "$prog" ] || return 0
+	config_get args "$cfg" args
+	config_get miboid "$cfg" miboid
+	echo "extend $miboid $name $prog $args" >> $CONFIGFILE
+}
+
+snmpd_disk_add() {
+        local cfg="$1"
+        local disk='disk'
+
+        config_get partition "$cfg" partition
+        [ -n "$partition" ] || return 0
+        config_get size "$cfg" size
+        [ -n "$size" ] || return 0
+        echo "$disk $partition $size" >> $CONFIGFILE
+}
+
+snmpd_engineid_add() {
+	local cfg="$1"
+
+	config_get engineid "$cfg" engineid
+	[ -n "$engineid" ] && echo "engineID $engineid" >> $CONFIGFILE
+	config_get engineidtype "$cfg" engineidtype
+	[ "$engineidtype" -ge 1 -a "$engineidtype" -le 3 ] && \
+		echo "engineIDType $engineidtype" >> $CONFIGFILE
+	config_get engineidnic "$cfg" engineidnic
+	[ -n "$engineidnic" ] && echo "engineIDNic $engineidnic" >> $CONFIGFILE
+}
+
+snmpd_sink_add() {
+	local cfg="$1"
+	local section="$2"
+	local community
+	local port
+	local host
+
+	config_get host "$cfg" host
+	[ -n "section" -a -n "$host" ] || return 0
+	# optional community
+	config_get community "$cfg" community
+	# optional port
+	config_get port "$cfg" port
+	port=${port:+:$port}
+	echo "$section $host$port $community" >> $CONFIGFILE
+}
+
+append_parm() {
+	local section="$1"
+	local option="$2"
+	local switch="$3"
+	local _loctmp
+	config_get _loctmp "$section" "$option"
+	[ -z "$_loctmp" ] && return 0
+	echo "$switch $_loctmp" >> $CONFIGFILE
+}
+
+append_authtrapenable() {
+	local section="$1"
+	local option="$2"
+	local switch="$3"
+	local _loctmp
+	config_get_bool _loctmp "$section" "$option"
+	[ -z "$_loctmp" ] && return 0
+	[ "$_loctmp" -gt 0 ] && echo "$switch $_loctmp" >> $CONFIGFILE
+}
+
+snmpd_setup_fw_rules() {
+	local net="$1"
+	local zone
+
+	zone=$(fw3 -q network "$net" 2>/dev/null)
+
+	local handled_zone
+	for handled_zone in $HANDLED_SNMP_ZONES; do
+		[ "$handled_zone" = "$zone" ] && return
+	done
+
+	json_add_object ""
+	json_add_string type rule
+	json_add_string src "$zone"
+	json_add_string proto udp
+	json_add_string dest_port 161
+	json_add_string target ACCEPT
+	json_close_object
+
+	HANDLED_SNMP_ZONES="$HANDLED_SNMP_ZONES $zone"
+}
+
+start_service() {
+	[ -f "$CONFIGFILE" ] && rm -f "$CONFIGFILE"
+
+	config_load snmpd
+
+	config_get_bool snmp_enabled general enabled 1
+	[ "$snmp_enabled" -eq 0 ] && return
+
+	procd_open_instance
+
+	config_foreach snmpd_agent_add agent
+	config_foreach snmpd_agentx_add agentx
+	config_foreach snmpd_system_add system
+	config_foreach snmpd_com2sec_add com2sec
+	config_foreach snmpd_com2sec6_add com2sec6
+	config_foreach snmpd_group_add group
+	config_foreach snmpd_view_add view
+	config_foreach snmpd_access_add access
+	config_foreach snmpd_trap_hostname_add trap_HostName
+	config_foreach snmpd_trap_ip_add trap_HostIP
+	config_foreach snmpd_access_default_add access_default
+	config_foreach snmpd_access_HostName_add access_HostName
+	config_foreach snmpd_access_HostIP_add access_HostIP
+	config_foreach snmpd_pass_add pass
+	config_foreach snmpd_exec_add exec
+	config_foreach snmpd_extend_add extend
+	config_foreach snmpd_disk_add disk
+	config_foreach snmpd_engineid_add engineid
+	append_parm trapcommunity community trapcommunity
+	config_foreach snmpd_sink_add trapsink trapsink
+	config_foreach snmpd_sink_add trap2sink trap2sink
+	config_foreach snmpd_sink_add informsink informsink
+	append_authtrapenable authtrapenable enable authtrapenable
+	append_parm v1trapaddress host v1trapaddress
+	append_parm trapsess trapsess trapsess
+
+	procd_set_param command $PROG -Lf /dev/null -f -r
+	procd_set_param file $CONFIGFILE
+	procd_set_param respawn
+
+	for iface in $(ls /sys/class/net 2>/dev/null); do
+		procd_append_param netdev "$iface"
+	done
+
+	procd_open_data
+
+	json_add_array firewall
+	config_list_foreach general network snmpd_setup_fw_rules
+	json_close_array
+
+	procd_close_data
+
+	procd_close_instance
+}
+
+stop_service() {
+	[ -f "$CONFIGFILE" ] || return
+	rm -f "$CONFIGFILE"
+	procd_set_config_changed firewall
+}
+
+service_triggers(){
+	local script=$(readlink "$initscript")
+	local name=$(basename ${script:-$initscript})
+
+	procd_open_trigger
+	procd_add_raw_trigger "interface.*" 2000 /etc/init.d/$name reload
+	procd_close_trigger
+
+	procd_add_reload_trigger 'snmpd'
+}
+
+service_started() {
+	[ "$snmp_enabled" -eq 0 ] && return
+	procd_set_config_changed firewall
+}
diff --git a/package/network/utils/net-snmp/files/snmptrapd.init b/package/network/utils/net-snmp/files/snmptrapd.init
new file mode 100644
index 0000000..43278a2
--- /dev/null
+++ b/package/network/utils/net-snmp/files/snmptrapd.init
@@ -0,0 +1,15 @@
+#!/bin/sh /etc/rc.common
+
+START=50
+
+USE_PROCD=1
+PROG="/usr/sbin/snmptrapd"
+
+start_service() {
+	procd_open_instance
+
+	procd_set_param command $PROG -Lf /dev/null -f
+	procd_set_param respawn
+
+	procd_close_instance
+}
diff --git a/package/network/utils/net-snmp/patches/000-cross-compile.patch b/package/network/utils/net-snmp/patches/000-cross-compile.patch
new file mode 100644
index 0000000..730bdbc
--- /dev/null
+++ b/package/network/utils/net-snmp/patches/000-cross-compile.patch
@@ -0,0 +1,47 @@
+From: Jo-Philipp Wich <jo@mein.io>
+Date: Fri, 6 Jan 2017 13:41:00 +0100
+Subject: [PATCH] configure: allow overriding hardcoded /usr/include/libnl3
+
+In a cross-compile setting we do not want to probe the host systems
+/usr/include path, therfore allow to disable this include path by passing
+ac_cv_header_netlink_netlink_h=yes to configure.
+
+Also disable the testing for libraries providing nl_connect when
+netsnmp_cv_func_nl_connect_LIBS is predefined since the proprietary
+NETSNMP_SEARCH_LIBS() macro will clobber the internal link flags upon
+encountering predefined cache variables, causing all subsequent configure
+link tests to fail due to a stray "no" word getting passed to the linker.
+
+Signed-off-by: Jo-Philipp Wich <jo@mein.io>
+--- a/configure.d/config_os_libs2
++++ b/configure.d/config_os_libs2
+@@ -254,14 +254,22 @@ if test "x$with_nl" != "xno"; then
+         )
+ 
+         netsnmp_save_CPPFLAGS="$CPPFLAGS"
+-        CPPFLAGS="${LIBNL3_CFLAGS} $CPPFLAGS"
+-        NETSNMP_SEARCH_LIBS(nl_connect, nl-3,
+-            [AC_CHECK_HEADERS(netlink/netlink.h)
+-            EXTERNAL_MIBGROUP_INCLUDES="$EXTERNAL_MIBGROUP_INCLUDES ${LIBNL3_CFLAGS}"],
+-            [CPPFLAGS="$netsnmp_save_CPPFLAGS"], [], [], [LMIBLIBS])
++        netsnmp_netlink_include_flags=""
+         if test "x$ac_cv_header_netlink_netlink_h" != xyes; then
+-            NETSNMP_SEARCH_LIBS(nl_connect, nl, [
+-                AC_CHECK_HEADERS(netlink/netlink.h)], [], [], LMIBLIBS)
++            netsnmp_netlink_include_flags="-I/usr/include/libnl3"
++        fi
++        CPPFLAGS="$netsnmp_netlink_include_flags $CPPFLAGS"
++        if test "x$netsnmp_cv_func_nl_connect_LIBS" = x; then
++            NETSNMP_SEARCH_LIBS(nl_connect, nl-3,
++                [AC_CHECK_HEADERS(netlink/netlink.h)
++                EXTERNAL_MIBGROUP_INCLUDES="$EXTERNAL_MIBGROUP_INCLUDES $netsnmp_netlink_include_flags"],
++                [CPPFLAGS="$netsnmp_save_CPPFLAGS"], [], [], [LMIBLIBS])
++            if test "x$ac_cv_header_netlink_netlink_h" != xyes; then
++                NETSNMP_SEARCH_LIBS(nl_connect, nl, [
++                    AC_CHECK_HEADERS(netlink/netlink.h)], [], [], LMIBLIBS)
++            fi
++        else
++            LMIBLIBS="$LMIBLIBS $netsnmp_cv_func_nl_connect_LIBS"
+         fi
+         if test "x$ac_cv_header_netlink_netlink_h" = xyes; then
+             AC_EGREP_HEADER([nl_socket_free], [netlink/socket.h],
diff --git a/package/network/utils/net-snmp/patches/100-debian-statistics.patch b/package/network/utils/net-snmp/patches/100-debian-statistics.patch
new file mode 100644
index 0000000..2b24d94
--- /dev/null
+++ b/package/network/utils/net-snmp/patches/100-debian-statistics.patch
@@ -0,0 +1,22 @@
+--- a/agent/mibgroup/mibII/interfaces.c
++++ b/agent/mibgroup/mibII/interfaces.c
+@@ -1588,6 +1588,10 @@ Interface_Scan_Init(void)
+         struct ifnet   *nnew;
+         char           *stats, *ifstart = line;
+ 
++	/* Ignore interfaces with no statistics. */
++	if (strstr(line, "No statistics available."))
++	    continue;
++
+         if (line[strlen(line) - 1] == '\n')
+             line[strlen(line) - 1] = '\0';
+ 
+@@ -1620,7 +1624,7 @@ Interface_Scan_Init(void)
+                                                &coll) != 5)) {
+             if ((scan_line_to_use == scan_line_2_2)
+                 && !strstr(line, "No statistics available"))
+-                snmp_log(LOG_ERR,
++                snmp_log(LOG_DEBUG,
+                          "/proc/net/dev data format error, line ==|%s|",
+                          line);
+             continue;
diff --git a/package/network/utils/net-snmp/patches/110-debian-makefiles.patch b/package/network/utils/net-snmp/patches/110-debian-makefiles.patch
new file mode 100644
index 0000000..2cb2715
--- /dev/null
+++ b/package/network/utils/net-snmp/patches/110-debian-makefiles.patch
@@ -0,0 +1,40 @@
+--- a/local/Makefile.in
++++ b/local/Makefile.in
+@@ -101,7 +101,7 @@ tkmib.made: $(srcdir)/tkmib
+ 
+ mib2c.made: $(srcdir)/mib2c
+ 	if test "x$(PERL)" != "x" ; then \
+-	  $(PERL) -p -e 's%^#!.*/perl.*%#!$(PERL)%;s#/usr/local/share/snmp#$(snmplibdir)#;' ${srcdir}/mib2c > mib2c.made; \
++	  $(PERL) -p -e 's%^#!.*/perl.*%#!$(PERL)%;s#/usr/local/share/snmp#$(snmplibdir)#;s#/usr/local/etc/snmp#$(SNMPCONFPATH)#;' ${srcdir}/mib2c > mib2c.made; \
+ 	else \
+ 	  touch mib2c.made; \
+         fi
+--- a/Makefile.top
++++ b/Makefile.top
+@@ -28,6 +28,7 @@ man8dir		= $(mandir)/man8
+ snmplibdir	= $(datadir)/snmp
+ mibdir		= $(snmplibdir)/mibs
+ persistentdir	= @PERSISTENT_DIRECTORY@
++sysconfdir	= @sysconfdir@
+ DESTDIR         = @INSTALL_PREFIX@
+ INSTALL_PREFIX  = $(DESTDIR)
+ 
+--- a/mibs/Makefile.in
++++ b/mibs/Makefile.in
+@@ -47,11 +47,15 @@ NETSNMPMIBS = NET-SNMP-TC.txt NET-SNMP-M
+ UCDMIBS = UCD-SNMP-MIB.txt UCD-DEMO-MIB.txt UCD-IPFWACC-MIB.txt \
+ 	UCD-DLMOD-MIB.txt UCD-DISKIO-MIB.txt
+ 
++EXTRAMIBS = BGP4-MIB.txt BRIDGE-MIB.txt GNOME-SMI.txt OSPF-MIB.txt \
++	OSPF-TRAP-MIB.txt RIPv2-MIB.txt SOURCE-ROUTING-MIB.txt \
++	LM-SENSORS-MIB.txt
++
+ DEFAULTMIBS = @default_mibs_install@
+ 
+ MIBS	= $(V1MIBS) $(V2MIBS) $(V3MIBS) $(RFCMIBS) \
+ 	$(AGENTMIBS) $(IANAMIBS) \
+-	$(NETSNMPMIBS) $(UCDMIBS) $(DEFAULTMIBS)
++	$(NETSNMPMIBS) $(UCDMIBS) $(DEFAULTMIBS) $(EXTRAMIBS)
+ 
+ all: standardall
+ 
diff --git a/package/network/utils/net-snmp/patches/120-debian-searchdirs.patch b/package/network/utils/net-snmp/patches/120-debian-searchdirs.patch
new file mode 100644
index 0000000..b5e377f
--- /dev/null
+++ b/package/network/utils/net-snmp/patches/120-debian-searchdirs.patch
@@ -0,0 +1,14 @@
+--- a/local/mib2c
++++ b/local/mib2c
+@@ -61,8 +61,9 @@ $currentlevel = -1;
+ if($ENV{MIB2C_DIR}) {
+    push @def_search_dirs, split(/:/, $ENV{MIB2C_DIR});
+ }
+-push @def_search_dirs, "/usr/local/share/snmp/";
+-push @def_search_dirs, "/usr/local/share/snmp/mib2c-data";
++push @def_search_dirs, "/etc/snmp/";
++push @def_search_dirs, "/usr/share/snmp/";
++push @def_search_dirs, "/usr/share/snmp/mib2c-data";
+ push @def_search_dirs, "./mib2c-conf.d";
+ 
+ sub usage {
diff --git a/package/network/utils/net-snmp/patches/130-debian-extramibs.patch b/package/network/utils/net-snmp/patches/130-debian-extramibs.patch
new file mode 100644
index 0000000..48fb907
--- /dev/null
+++ b/package/network/utils/net-snmp/patches/130-debian-extramibs.patch
@@ -0,0 +1,5183 @@
+--- /dev/null
++++ b/mibs/BGP4-MIB.txt
+@@ -0,0 +1,929 @@
++    BGP4-MIB DEFINITIONS ::= BEGIN
++
++        IMPORTS
++            MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE,
++            IpAddress, Integer32, Counter32, Gauge32, mib-2
++                FROM SNMPv2-SMI
++            MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP
++                FROM SNMPv2-CONF;
++
++        bgp MODULE-IDENTITY
++            LAST-UPDATED "9902100000Z"
++            ORGANIZATION "IETF IDR Working Group"
++            CONTACT-INFO "E-mail:  idr@merit.net
++
++                          Susan Hares  (Editor)
++                          Merit Network
++                          4251 Plymouth Road
++                          Suite C
++                          Ann Arbor, MI 48105-2785
++                          Tel: +1 734 936 2095
++                          Fax: +1 734 647 3185
++                          E-mail: skh@merit.edu
++
++                          Jeff Johnson (Editor)
++                          RedBack Networks, Inc.
++                          1389 Moffett Park Drive
++                          Sunnyvale, CA  94089-1134
++                          Tel: +1 408 548 3516
++                          Fax: +1 408 548 3599
++                          E-mail: jeff@redback.com"
++            DESCRIPTION
++                    "The MIB module for BGP-4."
++            REVISION    "9902100000Z"
++            DESCRIPTION
++                    "Corrected duplicate OBJECT IDENTIFIER
++                     assignment in the conformance information."
++            REVISION    "9601080000Z"
++            DESCRIPTION
++                    "1) Fixed the definitions of the traps to
++                     make them equivalent to their initial
++                     definition in RFC 1269.
++                     2) Added compliance and conformance info."
++            ::= { mib-2 15 }
++
++        bgpVersion OBJECT-TYPE
++            SYNTAX     OCTET STRING (SIZE (1..255))
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "Vector of supported BGP protocol version
++                    numbers.  Each peer negotiates the version
++                    from this vector.  Versions are identified
++                    via the string of bits contained within this
++                    object.  The first octet contains bits 0 to
++                    7, the second octet contains bits 8 to 15,
++                    and so on, with the most significant bit
++                    referring to the lowest bit number in the
++                    octet (e.g., the MSB of the first octet
++                    refers to bit 0).  If a bit, i, is present
++                    and set, then the version (i+1) of the BGP
++                    is supported."
++            ::= { bgp 1 }
++
++        bgpLocalAs OBJECT-TYPE
++            SYNTAX     INTEGER (0..65535)
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The local autonomous system number."
++            ::= { bgp 2 }
++
++
++
++        -- BGP Peer table.  This table contains, one entry per BGP
++        -- peer, information about the BGP peer.
++
++        bgpPeerTable OBJECT-TYPE
++            SYNTAX     SEQUENCE OF BgpPeerEntry
++            MAX-ACCESS not-accessible
++            STATUS     current
++            DESCRIPTION
++                    "BGP peer table.  This table contains,
++                    one entry per BGP peer, information about the
++                    connections with BGP peers."
++            ::= { bgp 3 }
++
++        bgpPeerEntry OBJECT-TYPE
++            SYNTAX     BgpPeerEntry
++            MAX-ACCESS not-accessible
++            STATUS     current
++            DESCRIPTION
++                    "Entry containing information about the
++                    connection with a BGP peer."
++            INDEX { bgpPeerRemoteAddr }
++            ::= { bgpPeerTable 1 }
++
++        BgpPeerEntry ::= SEQUENCE {
++                bgpPeerIdentifier
++                    IpAddress,
++                bgpPeerState
++                    INTEGER,
++                bgpPeerAdminStatus
++                    INTEGER,
++                bgpPeerNegotiatedVersion
++                    Integer32,
++                bgpPeerLocalAddr
++                    IpAddress,
++                bgpPeerLocalPort
++                    INTEGER,
++                bgpPeerRemoteAddr
++                    IpAddress,
++                bgpPeerRemotePort
++                    INTEGER,
++                bgpPeerRemoteAs
++                    INTEGER,
++                bgpPeerInUpdates
++                    Counter32,
++                bgpPeerOutUpdates
++                    Counter32,
++                bgpPeerInTotalMessages
++                    Counter32,
++                bgpPeerOutTotalMessages
++                    Counter32,
++                bgpPeerLastError
++                    OCTET STRING,
++                bgpPeerFsmEstablishedTransitions
++                    Counter32,
++                bgpPeerFsmEstablishedTime
++                    Gauge32,
++                bgpPeerConnectRetryInterval
++                    INTEGER,
++                bgpPeerHoldTime
++                    INTEGER,
++                bgpPeerKeepAlive
++                    INTEGER,
++                bgpPeerHoldTimeConfigured
++                    INTEGER,
++                bgpPeerKeepAliveConfigured
++                    INTEGER,
++                bgpPeerMinASOriginationInterval
++                    INTEGER,
++                bgpPeerMinRouteAdvertisementInterval
++                    INTEGER,
++                bgpPeerInUpdateElapsedTime
++                    Gauge32
++                }
++
++        bgpPeerIdentifier OBJECT-TYPE
++            SYNTAX     IpAddress
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The BGP Identifier of this entry's BGP peer."
++            ::= { bgpPeerEntry 1 }
++
++        bgpPeerState OBJECT-TYPE
++            SYNTAX     INTEGER {
++                                idle(1),
++                                connect(2),
++                                active(3),
++                                opensent(4),
++                                openconfirm(5),
++                                established(6)
++                       }
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The BGP peer connection state."
++            ::= { bgpPeerEntry 2 }
++
++        bgpPeerAdminStatus OBJECT-TYPE
++            SYNTAX     INTEGER {
++                                stop(1),
++                                start(2)
++                       }
++            MAX-ACCESS read-write
++            STATUS     current
++            DESCRIPTION
++                    "The desired state of the BGP connection.  A
++                    transition from 'stop' to 'start' will cause
++                    the BGP Start Event to be generated.  A
++                    transition from 'start' to 'stop' will cause
++                    the BGP Stop Event to be generated.  This
++                    parameter can be used to restart BGP peer
++                    connections.  Care should be used in providing
++                    write access to this object without adequate
++                    authentication."
++            ::= { bgpPeerEntry 3 }
++
++        bgpPeerNegotiatedVersion OBJECT-TYPE
++            SYNTAX     Integer32
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The negotiated version of BGP running between
++                    the two peers."
++            ::= { bgpPeerEntry 4 }
++
++        bgpPeerLocalAddr OBJECT-TYPE
++            SYNTAX     IpAddress
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The local IP address of this entry's BGP
++                    connection."
++            ::= { bgpPeerEntry 5 }
++
++        bgpPeerLocalPort OBJECT-TYPE
++            SYNTAX     INTEGER (0..65535)
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The local port for the TCP connection between
++                    the BGP peers."
++            ::= { bgpPeerEntry 6 }
++
++        bgpPeerRemoteAddr OBJECT-TYPE
++            SYNTAX     IpAddress
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The remote IP address of this entry's BGP
++                    peer."
++            ::= { bgpPeerEntry 7 }
++
++        bgpPeerRemotePort OBJECT-TYPE
++            SYNTAX     INTEGER (0..65535)
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The remote port for the TCP connection between
++                    the BGP peers.  Note that the objects
++                    bgpPeerLocalAddr, bgpPeerLocalPort,
++                    bgpPeerRemoteAddr and bgpPeerRemotePort
++                    provide the appropriate reference to the
++                    standard MIB TCP connection table."
++            ::= { bgpPeerEntry 8 }
++
++        bgpPeerRemoteAs OBJECT-TYPE
++            SYNTAX     INTEGER (0..65535)
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The remote autonomous system number."
++            ::= { bgpPeerEntry 9 }
++
++        bgpPeerInUpdates OBJECT-TYPE
++            SYNTAX     Counter32
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The number of BGP UPDATE messages received on
++                    this connection.  This object should be
++                    initialized to zero (0) when the connection is
++                    established."
++            ::= { bgpPeerEntry 10 }
++
++        bgpPeerOutUpdates OBJECT-TYPE
++            SYNTAX     Counter32
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The number of BGP UPDATE messages transmitted
++                    on this connection.  This object should be
++                    initialized to zero (0) when the connection is
++                    established."
++            ::= { bgpPeerEntry 11 }
++
++        bgpPeerInTotalMessages OBJECT-TYPE
++            SYNTAX     Counter32
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The total number of messages received from the
++                    remote peer on this connection.  This object
++                    should be initialized to zero when the
++                    connection is established."
++            ::= { bgpPeerEntry 12 }
++
++        bgpPeerOutTotalMessages OBJECT-TYPE
++            SYNTAX     Counter32
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The total number of messages transmitted to
++                    the remote peer on this connection.  This object
++                    should be initialized to zero when the
++                    connection is established."
++            ::= { bgpPeerEntry 13 }
++
++        bgpPeerLastError OBJECT-TYPE
++            SYNTAX     OCTET STRING (SIZE (2))
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The last error code and subcode seen by this
++                    peer on this connection.  If no error has
++                    occurred, this field is zero.  Otherwise, the
++                    first byte of this two byte OCTET STRING
++                    contains the error code, and the second byte
++                    contains the subcode."
++            ::= { bgpPeerEntry 14 }
++
++        bgpPeerFsmEstablishedTransitions OBJECT-TYPE
++            SYNTAX     Counter32
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The total number of times the BGP FSM
++                    transitioned into the established state."
++            ::= { bgpPeerEntry 15 }
++
++        bgpPeerFsmEstablishedTime OBJECT-TYPE
++            SYNTAX     Gauge32
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "This timer indicates how long (in seconds) this
++                    peer has been in the Established state or how long
++                    since this peer was last in the Established state.
++                    It is set to zero when a new peer is configured or
++                    the router is booted."
++            ::= { bgpPeerEntry 16 }
++
++        bgpPeerConnectRetryInterval OBJECT-TYPE
++            SYNTAX     INTEGER (1..65535)
++            MAX-ACCESS read-write
++            STATUS     current
++            DESCRIPTION
++                    "Time interval in seconds for the ConnectRetry
++                    timer.  The suggested value for this timer is
++                    120 seconds."
++            ::= { bgpPeerEntry 17 }
++
++        bgpPeerHoldTime OBJECT-TYPE
++            SYNTAX     INTEGER  ( 0 | 3..65535 )
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "Time interval in seconds for the Hold Timer
++                    established with the peer.  The value of this
++                    object is calculated by this BGP speaker by
++                    using the smaller of the value in
++                    bgpPeerHoldTimeConfigured and the Hold Time
++                    received in the OPEN message.  This value
++                    must be at lease three seconds if it is not
++                    zero (0) in which case the Hold Timer has
++                    not been established with the peer, or, the
++                    value of bgpPeerHoldTimeConfigured is zero (0)."
++            ::= { bgpPeerEntry 18 }
++
++        bgpPeerKeepAlive OBJECT-TYPE
++            SYNTAX     INTEGER ( 0 | 1..21845 )
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "Time interval in seconds for the KeepAlive
++                    timer established with the peer.  The value of
++                    this object is calculated by this BGP speaker
++                    such that, when compared with bgpPeerHoldTime,
++                    it has the same proportion as what
++                    bgpPeerKeepAliveConfigured has when compared
++                    with bgpPeerHoldTimeConfigured.  If the value
++                    of this object is zero (0), it indicates that
++                    the KeepAlive timer has not been established
++                    with the peer, or, the value of
++                    bgpPeerKeepAliveConfigured is zero (0)."
++            ::= { bgpPeerEntry 19 }
++
++        bgpPeerHoldTimeConfigured OBJECT-TYPE
++            SYNTAX     INTEGER ( 0 | 3..65535 )
++            MAX-ACCESS read-write
++            STATUS     current
++            DESCRIPTION
++                    "Time interval in seconds for the Hold Time
++                    configured for this BGP speaker with this peer.
++                    This value is placed in an OPEN message sent to
++                    this peer by this BGP speaker, and is compared
++                    with the Hold Time field in an OPEN message
++                    received from the peer when determining the Hold
++                    Time (bgpPeerHoldTime) with the peer.  This value
++                    must not be less than three seconds if it is not
++                    zero (0) in which case the Hold Time is NOT to be
++                    established with the peer.  The suggested value for
++                    this timer is 90 seconds."
++            ::= { bgpPeerEntry 20 }
++
++        bgpPeerKeepAliveConfigured OBJECT-TYPE
++            SYNTAX     INTEGER ( 0 | 1..21845 )
++            MAX-ACCESS read-write
++            STATUS     current
++            DESCRIPTION
++                    "Time interval in seconds for the KeepAlive timer
++                    configured for this BGP speaker with this peer.
++                    The value of this object will only determine the
++                    KEEPALIVE messages' frequency relative to the value
++                    specified in bgpPeerHoldTimeConfigured; the actual
++                    time interval for the KEEPALIVE messages is
++                    indicated by bgpPeerKeepAlive.  A reasonable
++                    maximum value for this timer would be configured to
++                    be one third of that of bgpPeerHoldTimeConfigured.
++                    If the value of this object is zero (0), no
++                    periodical KEEPALIVE messages are sent to the peer
++                    after the BGP connection has been established.  The
++                    suggested value for this timer is 30 seconds."
++            ::= { bgpPeerEntry 21 }
++
++        bgpPeerMinASOriginationInterval OBJECT-TYPE
++            SYNTAX     INTEGER (1..65535)
++            MAX-ACCESS read-write
++            STATUS     current
++            DESCRIPTION
++                    "Time interval in seconds for the
++                    MinASOriginationInterval timer.
++                    The suggested value for this timer is 15 seconds."
++            ::= { bgpPeerEntry 22 }
++
++        bgpPeerMinRouteAdvertisementInterval OBJECT-TYPE
++            SYNTAX     INTEGER (1..65535)
++            MAX-ACCESS read-write
++            STATUS     current
++            DESCRIPTION
++                    "Time interval in seconds for the
++                    MinRouteAdvertisementInterval timer.
++                    The suggested value for this timer is 30 seconds."
++            ::= { bgpPeerEntry 23 }
++
++        bgpPeerInUpdateElapsedTime OBJECT-TYPE
++            SYNTAX     Gauge32
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "Elapsed time in seconds since the last BGP
++                    UPDATE message was received from the peer.
++                    Each time bgpPeerInUpdates is incremented,
++                    the value of this object is set to zero (0)."
++            ::= { bgpPeerEntry 24 }
++
++
++
++        bgpIdentifier OBJECT-TYPE
++            SYNTAX     IpAddress
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The BGP Identifier of local system."
++            ::= { bgp 4 }
++
++
++
++        -- Received Path Attribute Table.  This table contains,
++        -- one entry per path to a network, path attributes
++        -- received from all peers running BGP version 3 or less.
++        -- This table is obsolete, having been replaced in
++        -- functionality with the bgp4PathAttrTable.
++
++        bgpRcvdPathAttrTable OBJECT-TYPE
++            SYNTAX     SEQUENCE OF BgpPathAttrEntry
++            MAX-ACCESS not-accessible
++            STATUS     obsolete
++            DESCRIPTION
++                    "The BGP Received Path Attribute Table contains
++                    information about paths to destination networks
++                    received from all peers running BGP version 3 or
++                    less."
++            ::= { bgp 5 }
++
++        bgpPathAttrEntry OBJECT-TYPE
++            SYNTAX     BgpPathAttrEntry
++            MAX-ACCESS not-accessible
++            STATUS     obsolete
++            DESCRIPTION
++                    "Information about a path to a network."
++            INDEX { bgpPathAttrDestNetwork,
++                    bgpPathAttrPeer        }
++            ::= { bgpRcvdPathAttrTable 1 }
++
++        BgpPathAttrEntry ::= SEQUENCE {
++            bgpPathAttrPeer
++                 IpAddress,
++            bgpPathAttrDestNetwork
++                 IpAddress,
++            bgpPathAttrOrigin
++                 INTEGER,
++            bgpPathAttrASPath
++                 OCTET STRING,
++            bgpPathAttrNextHop
++                 IpAddress,
++            bgpPathAttrInterASMetric
++                 Integer32
++        }
++
++        bgpPathAttrPeer OBJECT-TYPE
++            SYNTAX     IpAddress
++            MAX-ACCESS read-only
++            STATUS     obsolete
++            DESCRIPTION
++                    "The IP address of the peer where the path
++                    information was learned."
++            ::= { bgpPathAttrEntry 1 }
++
++        bgpPathAttrDestNetwork OBJECT-TYPE
++            SYNTAX     IpAddress
++            MAX-ACCESS read-only
++            STATUS     obsolete
++            DESCRIPTION
++                    "The address of the destination network."
++            ::= { bgpPathAttrEntry 2 }
++
++        bgpPathAttrOrigin OBJECT-TYPE
++            SYNTAX     INTEGER {
++                           igp(1),-- networks are interior
++                           egp(2),-- networks learned via EGP
++                           incomplete(3) -- undetermined
++                       }
++            MAX-ACCESS read-only
++            STATUS     obsolete
++            DESCRIPTION
++                 "The ultimate origin of the path information."
++            ::= { bgpPathAttrEntry 3 }
++
++        bgpPathAttrASPath OBJECT-TYPE
++            SYNTAX     OCTET STRING (SIZE (2..255))
++            MAX-ACCESS read-only
++            STATUS     obsolete
++            DESCRIPTION
++                    "The set of ASs that must be traversed to reach
++                    the network.  This object is probably best
++                    represented as SEQUENCE OF INTEGER.  For SMI
++                    compatibility, though, it is represented as
++                    OCTET STRING.  Each AS is represented as a pair
++                    of octets according to the following algorithm:
++
++                        first-byte-of-pair = ASNumber / 256;
++                        second-byte-of-pair = ASNumber & 255;"
++            ::= { bgpPathAttrEntry 4 }
++
++        bgpPathAttrNextHop OBJECT-TYPE
++            SYNTAX     IpAddress
++            MAX-ACCESS read-only
++            STATUS     obsolete
++            DESCRIPTION
++                    "The address of the border router that should
++                    be used for the destination network."
++            ::= { bgpPathAttrEntry 5 }
++
++        bgpPathAttrInterASMetric OBJECT-TYPE
++            SYNTAX     Integer32
++            MAX-ACCESS read-only
++            STATUS     obsolete
++            DESCRIPTION
++                    "The optional inter-AS metric.  If this
++                    attribute has not been provided for this route,
++                    the value for this object is 0."
++            ::= { bgpPathAttrEntry 6 }
++
++
++
++        -- BGP-4 Received Path Attribute Table.  This table contains,
++        -- one entry per path to a network, path attributes
++        -- received from all peers running BGP-4.
++
++        bgp4PathAttrTable OBJECT-TYPE
++            SYNTAX     SEQUENCE OF Bgp4PathAttrEntry
++            MAX-ACCESS not-accessible
++            STATUS     current
++            DESCRIPTION
++                    "The BGP-4 Received Path Attribute Table contains
++                    information about paths to destination networks
++                    received from all BGP4 peers."
++            ::= { bgp 6 }
++
++        bgp4PathAttrEntry OBJECT-TYPE
++            SYNTAX     Bgp4PathAttrEntry
++            MAX-ACCESS not-accessible
++            STATUS     current
++            DESCRIPTION
++                    "Information about a path to a network."
++            INDEX { bgp4PathAttrIpAddrPrefix,
++                    bgp4PathAttrIpAddrPrefixLen,
++                    bgp4PathAttrPeer            }
++            ::= { bgp4PathAttrTable 1 }
++
++        Bgp4PathAttrEntry ::= SEQUENCE {
++            bgp4PathAttrPeer
++                 IpAddress,
++            bgp4PathAttrIpAddrPrefixLen
++                 INTEGER,
++            bgp4PathAttrIpAddrPrefix
++                 IpAddress,
++            bgp4PathAttrOrigin
++                 INTEGER,
++            bgp4PathAttrASPathSegment
++                 OCTET STRING,
++            bgp4PathAttrNextHop
++                 IpAddress,
++            bgp4PathAttrMultiExitDisc
++                 INTEGER,
++            bgp4PathAttrLocalPref
++                 INTEGER,
++            bgp4PathAttrAtomicAggregate
++                 INTEGER,
++            bgp4PathAttrAggregatorAS
++                 INTEGER,
++            bgp4PathAttrAggregatorAddr
++                 IpAddress,
++            bgp4PathAttrCalcLocalPref
++                 INTEGER,
++            bgp4PathAttrBest
++                 INTEGER,
++            bgp4PathAttrUnknown
++                 OCTET STRING
++        }
++
++        bgp4PathAttrPeer OBJECT-TYPE
++            SYNTAX     IpAddress
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The IP address of the peer where the path
++                    information was learned."
++            ::= { bgp4PathAttrEntry 1 }
++        bgp4PathAttrIpAddrPrefixLen OBJECT-TYPE
++            SYNTAX     INTEGER (0..32)
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "Length in bits of the IP address prefix in the
++                    Network Layer Reachability Information field."
++            ::= { bgp4PathAttrEntry 2 }
++
++        bgp4PathAttrIpAddrPrefix OBJECT-TYPE
++            SYNTAX     IpAddress
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "An IP address prefix in the Network Layer
++                    Reachability Information field.  This object
++                    is an IP address containing the prefix with
++                    length specified by bgp4PathAttrIpAddrPrefixLen.
++                    Any bits beyond the length specified by
++                    bgp4PathAttrIpAddrPrefixLen are zeroed."
++            ::= { bgp4PathAttrEntry 3 }
++
++        bgp4PathAttrOrigin OBJECT-TYPE
++            SYNTAX     INTEGER {
++                                 igp(1),-- networks are interior
++                                 egp(2),-- networks learned via EGP
++                                 incomplete(3) -- undetermined
++                               }
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The ultimate origin of the path information."
++            ::= { bgp4PathAttrEntry 4 }
++
++        bgp4PathAttrASPathSegment OBJECT-TYPE
++            SYNTAX     OCTET STRING (SIZE (2..255))
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The sequence of AS path segments.  Each AS
++                    path segment is represented by a triple
++                    <type, length, value>.
++
++                    The type is a 1-octet field which has two
++                    possible values:
++                         1      AS_SET: unordered set of ASs a
++                                     route in the UPDATE message
++                                     has traversed
++                         2      AS_SEQUENCE: ordered set of ASs
++                                     a route in the UPDATE message
++                                     has traversed.
++
++                    The length is a 1-octet field containing the
++                    number of ASs in the value field.
++
++                    The value field contains one or more AS
++                    numbers, each AS is represented in the octet
++                    string as a pair of octets according to the
++                    following algorithm:
++
++                        first-byte-of-pair = ASNumber / 256;
++                        second-byte-of-pair = ASNumber & 255;"
++            ::= { bgp4PathAttrEntry 5 }
++
++        bgp4PathAttrNextHop OBJECT-TYPE
++            SYNTAX     IpAddress
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The address of the border router that should
++                    be used for the destination network."
++            ::= { bgp4PathAttrEntry 6 }
++
++        bgp4PathAttrMultiExitDisc OBJECT-TYPE
++            SYNTAX     INTEGER (-1..2147483647)
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "This metric is used to discriminate between
++                    multiple exit points to an adjacent autonomous
++                    system.  A value of -1 indicates the absence of
++                    this attribute."
++            ::= { bgp4PathAttrEntry 7 }
++
++        bgp4PathAttrLocalPref OBJECT-TYPE
++            SYNTAX     INTEGER (-1..2147483647)
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The originating BGP4 speaker's degree of
++                    preference for an advertised route.  A value of
++                    -1 indicates the absence of this attribute."
++            ::= { bgp4PathAttrEntry 8 }
++
++        bgp4PathAttrAtomicAggregate OBJECT-TYPE
++            SYNTAX     INTEGER {
++                           lessSpecificRrouteNotSelected(1),
++                           lessSpecificRouteSelected(2)
++                       }
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "Whether or not a system has selected
++                    a less specific route without selecting a
++                    more specific route."
++            ::= { bgp4PathAttrEntry 9 }
++
++        bgp4PathAttrAggregatorAS OBJECT-TYPE
++            SYNTAX     INTEGER (0..65535)
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The AS number of the last BGP4 speaker that
++                    performed route aggregation.  A value of zero (0)
++                    indicates the absence of this attribute."
++            ::= { bgp4PathAttrEntry 10 }
++
++        bgp4PathAttrAggregatorAddr OBJECT-TYPE
++            SYNTAX     IpAddress
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The IP address of the last BGP4 speaker that
++                     performed route aggregation.  A value of
++                     0.0.0.0 indicates the absence of this attribute."
++            ::= { bgp4PathAttrEntry 11 }
++
++        bgp4PathAttrCalcLocalPref OBJECT-TYPE
++            SYNTAX     INTEGER (-1..2147483647)
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "The degree of preference calculated by the
++                    receiving BGP4 speaker for an advertised route.
++                    A value of -1 indicates the absence of this
++                    attribute."
++            ::= { bgp4PathAttrEntry 12 }
++
++        bgp4PathAttrBest OBJECT-TYPE
++            SYNTAX     INTEGER {
++                           false(1),-- not chosen as best route
++                           true(2) -- chosen as best route
++                       }
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "An indication of whether or not this route
++                    was chosen as the best BGP4 route."
++            ::= { bgp4PathAttrEntry 13 }
++
++        bgp4PathAttrUnknown OBJECT-TYPE
++            SYNTAX     OCTET STRING (SIZE(0..255))
++            MAX-ACCESS read-only
++            STATUS     current
++            DESCRIPTION
++                    "One or more path attributes not understood
++                     by this BGP4 speaker.  Size zero (0) indicates
++                     the absence of such attribute(s).  Octets
++                     beyond the maximum size, if any, are not
++                     recorded by this object."
++            ::= { bgp4PathAttrEntry 14 }
++
++
++        -- Traps.
++
++        -- note that in RFC 1657, bgpTraps was incorrectly
++        -- assigned a value of { bgp 7 }, and each of the
++        -- traps had the bgpPeerRemoteAddr object inappropriately
++        -- removed from their OBJECTS clause.  The following
++        -- definitions restore the semantics of the traps as
++        -- they were initially defined in RFC 1269.
++
++        -- { bgp 7 } is unused
++
++        bgpTraps          OBJECT IDENTIFIER ::= { bgp 0 }
++
++        bgpEstablished NOTIFICATION-TYPE
++            OBJECTS { bgpPeerRemoteAddr,
++                      bgpPeerLastError,
++                      bgpPeerState      }
++            STATUS  current
++            DESCRIPTION
++                    "The BGP Established event is generated when
++                    the BGP FSM enters the ESTABLISHED state."
++            ::= { bgpTraps 1 }
++
++        bgpBackwardTransition NOTIFICATION-TYPE
++            OBJECTS { bgpPeerRemoteAddr,
++                      bgpPeerLastError,
++                      bgpPeerState      }
++            STATUS  current
++            DESCRIPTION
++                    "The BGPBackwardTransition Event is generated
++                    when the BGP FSM moves from a higher numbered
++                    state to a lower numbered state."
++            ::= { bgpTraps 2 }
++
++        -- conformance information
++
++        bgpMIBConformance OBJECT IDENTIFIER ::= { bgp 8 }
++        bgpMIBCompliances OBJECT IDENTIFIER ::= { bgpMIBConformance 1 }
++        bgpMIBGroups      OBJECT IDENTIFIER ::= { bgpMIBConformance 2 }
++
++        -- compliance statements
++
++        bgpMIBCompliance MODULE-COMPLIANCE
++            STATUS  current
++            DESCRIPTION
++                    "The compliance statement for entities which
++                     implement the BGP4 mib."
++            MODULE  -- this module
++                MANDATORY-GROUPS { bgp4MIBGlobalsGroup,
++                                   bgp4MIBPeerGroup,
++                                   bgp4MIBPathAttrGroup,
++                                   bgp4MIBNotificationGroup }
++            ::= { bgpMIBCompliances 1 }
++
++        -- units of conformance
++
++        bgp4MIBGlobalsGroup OBJECT-GROUP
++            OBJECTS { bgpVersion,
++                      bgpLocalAs,
++                      bgpIdentifier }
++            STATUS  current
++            DESCRIPTION
++                    "A collection of objects providing information
++                     on global BGP state."
++            ::= { bgpMIBGroups 1 }
++
++        bgp4MIBPeerGroup OBJECT-GROUP
++            OBJECTS { bgpPeerIdentifier,
++                      bgpPeerState,
++                      bgpPeerAdminStatus,
++                      bgpPeerNegotiatedVersion,
++                      bgpPeerLocalAddr,
++                      bgpPeerLocalPort,
++                      bgpPeerRemoteAddr,
++                      bgpPeerRemotePort,
++                      bgpPeerRemoteAs,
++                      bgpPeerInUpdates,
++                      bgpPeerOutUpdates,
++                      bgpPeerInTotalMessages,
++                      bgpPeerOutTotalMessages,
++                      bgpPeerLastError,
++                      bgpPeerFsmEstablishedTransitions,
++                      bgpPeerFsmEstablishedTime,
++                      bgpPeerConnectRetryInterval,
++                      bgpPeerHoldTime,
++                      bgpPeerKeepAlive,
++                      bgpPeerHoldTimeConfigured,
++                      bgpPeerKeepAliveConfigured,
++                      bgpPeerMinASOriginationInterval,
++                      bgpPeerMinRouteAdvertisementInterval,
++                      bgpPeerInUpdateElapsedTime }
++            STATUS  current
++            DESCRIPTION
++                    "A collection of objects for managing
++                     BGP peers."
++            ::= { bgpMIBGroups 2 }
++
++        bgp4MIBRcvdPathAttrGroup OBJECT-GROUP
++            OBJECTS { bgpPathAttrPeer,
++                      bgpPathAttrDestNetwork,
++                      bgpPathAttrOrigin,
++                      bgpPathAttrASPath,
++                      bgpPathAttrNextHop,
++                      bgpPathAttrInterASMetric }
++            STATUS  obsolete
++            DESCRIPTION
++                    "A collection of objects for managing BGP
++                     path entries.
++
++                     This conformance group is obsolete,
++                     replaced by bgp4MIBPathAttrGroup."
++            ::= { bgpMIBGroups 3 }
++
++        bgp4MIBPathAttrGroup OBJECT-GROUP
++            OBJECTS { bgp4PathAttrPeer,
++                      bgp4PathAttrIpAddrPrefixLen,
++                      bgp4PathAttrIpAddrPrefix,
++                      bgp4PathAttrOrigin,
++                      bgp4PathAttrASPathSegment,
++                      bgp4PathAttrNextHop,
++                      bgp4PathAttrMultiExitDisc,
++                      bgp4PathAttrLocalPref,
++                      bgp4PathAttrAtomicAggregate,
++                      bgp4PathAttrAggregatorAS,
++                      bgp4PathAttrAggregatorAddr,
++                      bgp4PathAttrCalcLocalPref,
++                      bgp4PathAttrBest,
++                      bgp4PathAttrUnknown }
++            STATUS  current
++            DESCRIPTION
++                    "A collection of objects for managing
++                     BGP path entries."
++            ::= { bgpMIBGroups 4 }
++
++        bgp4MIBNotificationGroup NOTIFICATION-GROUP
++            NOTIFICATIONS { bgpEstablished,
++                            bgpBackwardTransition }
++            STATUS  current
++            DESCRIPTION
++                    "A collection of notifications for signaling
++                    changes in BGP peer relationships."
++            ::= { bgpMIBGroups 5 }
++
++    END
+--- /dev/null
++++ b/mibs/GNOME-SMI.txt
+@@ -0,0 +1,88 @@
++GNOME-SMI DEFINITIONS ::= BEGIN
++
++IMPORTS
++	MODULE-IDENTITY,
++	OBJECT-IDENTITY,
++	enterprises
++		FROM SNMPv2-SMI;
++
++gnome MODULE-IDENTITY
++	LAST-UPDATED "200709070000Z"
++	ORGANIZATION "GNOME project"
++	CONTACT-INFO
++		"GNU Network Object Model Environment project
++		
++		see http://www.gnome.org for contact persons of a particular
++		area or subproject of GNOME.
++
++		Administrative contact for MIB module:
++
++		Jochen Friedrich
++		Ramsaystr. 9
++		63450 Hanau
++		Germany 
++
++		email: jochen@scram.de"
++	DESCRIPTION
++		"The Structure of GNOME."
++
++	-- revision history
++
++	REVISION "200709070000Z"  -- Sep 07, 2007
++	DESCRIPTION
++		"Fixed wrong enterprise number (how comes this
++		typo was unnoticed for so long?)."
++
++	REVISION "200505070000Z"  -- May 07, 2005
++	DESCRIPTION
++		"Added gnomeLDAP subtree for LDAP definitions."
++
++	REVISION "200312070000Z"  -- December 07, 2003
++	DESCRIPTION
++		"Added gnomeSysadmin subtree for GNOME project system administration.
++		Updated contact info."
++
++	REVISION "9809010000Z"  -- September 01, 1998
++	DESCRIPTION
++		"Initial version."
++
++	::= { enterprises 3319 }	-- assigned by IANA
++
++gnomeProducts OBJECT-IDENTITY
++	STATUS	current
++	DESCRIPTION
++		"gnomeProducts is the root OBJECT IDENTIFIER from
++		which sysObjectID values are assigned."
++	::= { gnome 1 }
++
++gnomeMgmt OBJECT-IDENTITY
++	STATUS  current
++	DESCRIPTION
++		"gnomeMgmt defines the subtree for production GNOME related
++		MIB registrations."
++	::= { gnome 2 }
++
++gnomeTest OBJECT-IDENTITY
++	STATUS  current
++	DESCRIPTION
++		"gnomeTest defines the subtree for testing GNOME related
++		MIB registrations."
++	::= { gnome 3 }
++
++gnomeSysadmin OBJECT-IDENTITY
++	STATUS  current
++	DESCRIPTION
++		"gnomeSysadmin defines the subtree for GNOME related Sysadmin
++		MIB registrations."
++	::= { gnome 4 }
++
++gnomeLDAP OBJECT-IDENTITY
++	STATUS  current
++	DESCRIPTION
++		"gnomeLDAP defines the subtree for GNOME related LDAP
++		registrations."
++	::= { gnome 5 }
++
++-- more to come if necessary.
++
++END
+--- /dev/null
++++ b/mibs/OSPF-MIB.txt
+@@ -0,0 +1,2723 @@
++OSPF-MIB DEFINITIONS ::= BEGIN
++
++    IMPORTS
++            MODULE-IDENTITY, OBJECT-TYPE, Counter32, Gauge32,
++            Integer32, IpAddress
++                FROM SNMPv2-SMI
++            TEXTUAL-CONVENTION, TruthValue, RowStatus
++                FROM SNMPv2-TC
++            MODULE-COMPLIANCE, OBJECT-GROUP          FROM SNMPv2-CONF
++            mib-2                                    FROM RFC1213-MIB;
++
++--  This MIB module uses the extended OBJECT-TYPE macro as
++--  defined in [9].
++
++ospf MODULE-IDENTITY
++        LAST-UPDATED "9501201225Z" -- Fri Jan 20 12:25:50 PST 1995
++        ORGANIZATION "IETF OSPF Working Group"
++        CONTACT-INFO
++       "       Fred Baker
++       Postal: Cisco Systems
++               519 Lado Drive
++               Santa Barbara, California 93111
++       Tel:    +1 805 681 0115
++       E-Mail: fred@cisco.com
++
++               Rob Coltun
++       Postal: RainbowBridge Communications
++       Tel:    (301) 340-9416
++       E-Mail: rcoltun@rainbow-bridge.com"
++    DESCRIPTION
++       "The MIB module to describe the OSPF Version 2
++       Protocol"
++    ::= { mib-2 14 }
++
++--  The Area ID, in OSPF, has the same format as an IP Address,
++--  but has the function of defining a summarization point for
++--  Link State Advertisements
++
++AreaID ::= TEXTUAL-CONVENTION
++    STATUS      current
++    DESCRIPTION
++       "An OSPF Area Identifier."
++    SYNTAX      IpAddress
++
++
++--  The Router ID, in OSPF, has the same format as an IP Address,
++--  but identifies the router independent of its IP Address.
++
++RouterID ::= TEXTUAL-CONVENTION
++    STATUS      current
++    DESCRIPTION
++       "A OSPF Router Identifier."
++    SYNTAX      IpAddress
++
++
++--  The OSPF Metric is defined as an unsigned value in the range
++
++Metric ::= TEXTUAL-CONVENTION
++    STATUS      current
++    DESCRIPTION
++       "The OSPF Internal Metric."
++    SYNTAX      Integer32 (0..'FFFF'h)
++
++BigMetric ::= TEXTUAL-CONVENTION
++    STATUS      current
++    DESCRIPTION
++       "The OSPF External Metric."
++    SYNTAX      Integer32 (0..'FFFFFF'h)
++
++--  Status Values
++
++Status ::= TEXTUAL-CONVENTION
++    STATUS      current
++    DESCRIPTION
++       "The status of an interface: 'enabled' indicates that
++       it is willing to communicate with other OSPF Routers,
++       while 'disabled' indicates that it is not."
++    SYNTAX      INTEGER { enabled (1), disabled (2) }
++
++--  Time Durations measured in seconds
++
++PositiveInteger ::= TEXTUAL-CONVENTION
++    STATUS      current
++    DESCRIPTION
++       "A positive integer. Values in excess are precluded as
++       unnecessary and prone to interoperability issues."
++    SYNTAX      Integer32 (0..'7FFFFFFF'h)
++
++HelloRange ::= TEXTUAL-CONVENTION
++    STATUS      current
++    DESCRIPTION
++       "The range of intervals on which hello messages are
++       exchanged."
++    SYNTAX      Integer32 (1..'FFFF'h)
++
++UpToMaxAge ::= TEXTUAL-CONVENTION
++    STATUS      current
++    DESCRIPTION
++       "The values that one might find or configure for
++       variables bounded by the maximum age of an LSA."
++    SYNTAX      Integer32 (0..3600)
++
++
++--  The range of ifIndex
++
++InterfaceIndex ::= TEXTUAL-CONVENTION
++    STATUS      current
++    DESCRIPTION
++       "The range of ifIndex."
++    SYNTAX      Integer32
++
++
++--  Potential Priorities for the Designated Router Election
++
++DesignatedRouterPriority ::= TEXTUAL-CONVENTION
++    STATUS      current
++    DESCRIPTION
++       "The values defined for the priority of a system for
++       becoming the designated router."
++    SYNTAX      Integer32 (0..'FF'h)
++
++TOSType ::= TEXTUAL-CONVENTION
++    STATUS      current
++    DESCRIPTION
++       "Type of Service is defined as a mapping to the IP Type of
++       Service Flags as defined in the IP Forwarding Table MIB
++
++       +-----+-----+-----+-----+-----+-----+-----+-----+
++       |                 |                       |     |
++       |   PRECEDENCE    |    TYPE OF SERVICE    |  0  |
++       |                 |                       |     |
++       +-----+-----+-----+-----+-----+-----+-----+-----+
++
++                IP TOS                IP TOS
++           Field     Policy      Field     Policy
++
++           Contents    Code      Contents    Code
++           0 0 0 0  ==>   0      0 0 0 1  ==>   2
++           0 0 1 0  ==>   4      0 0 1 1  ==>   6
++           0 1 0 0  ==>   8      0 1 0 1  ==>  10
++           0 1 1 0  ==>  12      0 1 1 1  ==>  14
++           1 0 0 0  ==>  16      1 0 0 1  ==>  18
++           1 0 1 0  ==>  20      1 0 1 1  ==>  22
++           1 1 0 0  ==>  24      1 1 0 1  ==>  26
++           1 1 1 0  ==>  28      1 1 1 1  ==>  30
++
++       The remaining values are left for future definition."
++    SYNTAX      Integer32 (0..30)
++
++
++--  OSPF General Variables
++
++--      These parameters apply globally to the Router's
++--      OSPF Process.
++
++ospfGeneralGroup OBJECT IDENTIFIER ::= { ospf 1 }
++
++
++    ospfRouterId OBJECT-TYPE
++        SYNTAX   RouterID
++        MAX-ACCESS   read-write
++        STATUS   current
++        DESCRIPTION
++           "A  32-bit  integer  uniquely  identifying  the
++           router in the Autonomous System.
++
++           By  convention,  to  ensure  uniqueness,   this
++           should  default  to  the  value  of  one of the
++           router's IP interface addresses."
++       REFERENCE
++          "OSPF Version 2, C.1 Global parameters"
++      ::= { ospfGeneralGroup 1 }
++
++
++    ospfAdminStat OBJECT-TYPE
++        SYNTAX   Status
++        MAX-ACCESS   read-write
++        STATUS   current
++        DESCRIPTION
++           "The  administrative  status  of  OSPF  in  the
++           router.   The  value 'enabled' denotes that the
++           OSPF Process is active on at least  one  inter-
++           face;  'disabled'  disables  it  on  all inter-
++           faces."
++       ::= { ospfGeneralGroup 2 }
++
++    ospfVersionNumber OBJECT-TYPE
++        SYNTAX   INTEGER    { version2 (2) }
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The current version number of the OSPF  proto-
++           col is 2."
++       REFERENCE
++          "OSPF Version 2, Title"
++      ::= { ospfGeneralGroup 3 }
++
++
++    ospfAreaBdrRtrStatus OBJECT-TYPE
++        SYNTAX   TruthValue
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "A flag to note whether this router is an  area
++           border router."
++       REFERENCE
++          "OSPF Version 2, Section 3 Splitting the AS into
++          Areas"
++      ::= { ospfGeneralGroup 4 }
++
++
++    ospfASBdrRtrStatus OBJECT-TYPE
++        SYNTAX   TruthValue
++        MAX-ACCESS   read-write
++        STATUS   current
++        DESCRIPTION
++           "A flag to note whether this router is  config-
++           ured as an Autonomous System border router."
++       REFERENCE
++          "OSPF Version 2, Section 3.3  Classification  of
++          routers"
++      ::= { ospfGeneralGroup 5 }
++
++    ospfExternLsaCount OBJECT-TYPE
++        SYNTAX   Gauge32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The number of external (LS type 5)  link-state
++           advertisements in the link-state database."
++       REFERENCE
++          "OSPF Version 2, Appendix A.4.5 AS external link
++          advertisements"
++      ::= { ospfGeneralGroup 6 }
++
++
++    ospfExternLsaCksumSum OBJECT-TYPE
++        SYNTAX   Integer32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The 32-bit unsigned sum of the LS checksums of
++           the  external  link-state  advertisements  con-
++           tained in the link-state  database.   This  sum
++           can  be  used  to determine if there has been a
++           change in a router's link state  database,  and
++           to  compare  the  link-state  database  of  two
++           routers."
++       ::= { ospfGeneralGroup 7 }
++
++
++    ospfTOSSupport OBJECT-TYPE
++        SYNTAX   TruthValue
++        MAX-ACCESS   read-write
++        STATUS   current
++        DESCRIPTION
++           "The router's support for type-of-service rout-
++           ing."
++       REFERENCE
++          "OSPF Version 2,  Appendix  F.1.2  Optional  TOS
++          support"
++      ::= { ospfGeneralGroup 8 }
++
++    ospfOriginateNewLsas OBJECT-TYPE
++        SYNTAX   Counter32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The number of  new  link-state  advertisements
++           that  have been originated.  This number is in-
++           cremented each time the router originates a new
++           LSA."
++       ::= { ospfGeneralGroup 9 }
++
++
++    ospfRxNewLsas OBJECT-TYPE
++        SYNTAX   Counter32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The number of  link-state  advertisements  re-
++           ceived  determined  to  be  new instantiations.
++           This number does not include  newer  instantia-
++           tions  of self-originated link-state advertise-
++           ments."
++       ::= { ospfGeneralGroup 10 }
++
++    ospfExtLsdbLimit OBJECT-TYPE
++        SYNTAX   Integer32 (-1..'7FFFFFFF'h)
++        MAX-ACCESS   read-write
++        STATUS   current
++        DESCRIPTION
++           "The  maximum   number   of   non-default   AS-
++           external-LSAs entries that can be stored in the
++           link-state database.  If the value is -1,  then
++           there is no limit.
++
++           When the number of non-default AS-external-LSAs
++           in   a  router's  link-state  database  reaches
++           ospfExtLsdbLimit, the router  enters  Overflow-
++           State.   The   router  never  holds  more  than
++           ospfExtLsdbLimit  non-default  AS-external-LSAs
++           in  its  database. OspfExtLsdbLimit MUST be set
++           identically in all routers attached to the OSPF
++           backbone  and/or  any regular OSPF area. (i.e.,
++           OSPF stub areas and NSSAs are excluded)."
++       DEFVAL { -1 }
++       ::= { ospfGeneralGroup 11 }
++
++    ospfMulticastExtensions OBJECT-TYPE
++        SYNTAX   Integer32
++        MAX-ACCESS   read-write
++        STATUS   current
++        DESCRIPTION
++           "A Bit Mask indicating whether  the  router  is
++           forwarding  IP  multicast  (Class  D) datagrams
++           based on the algorithms defined in  the  Multi-
++           cast Extensions to OSPF.
++
++           Bit 0, if set, indicates that  the  router  can
++           forward  IP multicast datagrams in the router's
++           directly attached areas (called intra-area mul-
++           ticast routing).
++
++           Bit 1, if set, indicates that  the  router  can
++           forward  IP  multicast  datagrams  between OSPF
++           areas (called inter-area multicast routing).
++
++           Bit 2, if set, indicates that  the  router  can
++           forward  IP  multicast  datagrams between Auto-
++           nomous Systems (called inter-AS multicast rout-
++           ing).
++
++           Only certain combinations of bit  settings  are
++           allowed,  namely: 0 (no multicast forwarding is
++           enabled), 1 (intra-area multicasting  only),  3
++           (intra-area  and  inter-area  multicasting),  5
++           (intra-area and inter-AS  multicasting)  and  7
++           (multicasting  everywhere). By default, no mul-
++           ticast forwarding is enabled."
++       DEFVAL { 0 }
++       ::= { ospfGeneralGroup 12 }
++
++    ospfExitOverflowInterval OBJECT-TYPE
++        SYNTAX   PositiveInteger
++        MAX-ACCESS   read-write
++        STATUS   current
++        DESCRIPTION
++           "The number of  seconds  that,  after  entering
++           OverflowState,  a  router will attempt to leave
++           OverflowState. This allows the router to  again
++           originate  non-default  AS-external-LSAs.  When
++           set to 0, the router will not  leave  Overflow-
++           State until restarted."
++       DEFVAL { 0 }
++       ::= { ospfGeneralGroup 13 }
++
++
++    ospfDemandExtensions OBJECT-TYPE
++        SYNTAX   TruthValue
++        MAX-ACCESS   read-write
++        STATUS   current
++        DESCRIPTION
++           "The router's support for demand routing."
++       REFERENCE
++          "OSPF Version 2, Appendix on Demand Routing"
++      ::= { ospfGeneralGroup 14 }
++
++
++--      The OSPF Area Data Structure contains information
++--      regarding the various areas. The interfaces and
++--      virtual links are configured as part of these areas.
++--      Area 0.0.0.0, by definition, is the Backbone Area
++
++
++    ospfAreaTable OBJECT-TYPE
++        SYNTAX   SEQUENCE OF OspfAreaEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "Information describing the configured  parame-
++           ters  and cumulative statistics of the router's
++           attached areas."
++       REFERENCE
++          "OSPF Version 2, Section 6  The Area Data Struc-
++          ture"
++      ::= { ospf 2 }
++
++
++    ospfAreaEntry OBJECT-TYPE
++        SYNTAX   OspfAreaEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "Information describing the configured  parame-
++           ters  and  cumulative  statistics of one of the
++           router's attached areas."
++       INDEX { ospfAreaId }
++       ::= { ospfAreaTable 1 }
++
++OspfAreaEntry ::=
++    SEQUENCE {
++        ospfAreaId
++            AreaID,
++        ospfAuthType
++            Integer32,
++        ospfImportAsExtern
++            INTEGER,
++        ospfSpfRuns
++            Counter32,
++        ospfAreaBdrRtrCount
++            Gauge32,
++        ospfAsBdrRtrCount
++            Gauge32,
++        ospfAreaLsaCount
++            Gauge32,
++        ospfAreaLsaCksumSum
++            Integer32,
++        ospfAreaSummary
++            INTEGER,
++        ospfAreaStatus
++            RowStatus
++              }
++
++    ospfAreaId OBJECT-TYPE
++        SYNTAX   AreaID
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "A 32-bit integer uniquely identifying an area.
++           Area ID 0.0.0.0 is used for the OSPF backbone."
++       REFERENCE
++          "OSPF Version 2, Appendix C.2 Area parameters"
++      ::= { ospfAreaEntry 1 }
++
++
++    ospfAuthType OBJECT-TYPE
++        SYNTAX   Integer32
++                    -- none (0),
++                    -- simplePassword (1)
++                    -- md5 (2)
++                    -- reserved for specification by IANA (> 2)
++        MAX-ACCESS   read-create
++        STATUS   obsolete
++        DESCRIPTION
++           "The authentication type specified for an area.
++           Additional authentication types may be assigned
++           locally on a per Area basis."
++       REFERENCE
++          "OSPF Version 2, Appendix E Authentication"
++      DEFVAL { 0 }        -- no authentication, by default
++      ::= { ospfAreaEntry 2 }
++
++    ospfImportAsExtern OBJECT-TYPE
++        SYNTAX   INTEGER    {
++                    importExternal (1),
++                    importNoExternal (2),
++                    importNssa (3)
++                  }
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The area's support for importing  AS  external
++           link- state advertisements."
++       REFERENCE
++          "OSPF Version 2, Appendix C.2 Area parameters"
++      DEFVAL { importExternal }
++      ::= { ospfAreaEntry 3 }
++
++
++    ospfSpfRuns OBJECT-TYPE
++        SYNTAX   Counter32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The number of times that the intra-area  route
++           table  has  been  calculated  using this area's
++           link-state database.  This  is  typically  done
++           using Dijkstra's algorithm."
++       ::= { ospfAreaEntry 4 }
++
++
++    ospfAreaBdrRtrCount OBJECT-TYPE
++        SYNTAX   Gauge32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The total number of area border routers reach-
++           able within this area.  This is initially zero,
++           and is calculated in each SPF Pass."
++       ::= { ospfAreaEntry 5 }
++
++    ospfAsBdrRtrCount OBJECT-TYPE
++        SYNTAX   Gauge32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The total number of Autonomous  System  border
++           routers  reachable  within  this area.  This is
++           initially zero, and is calculated in  each  SPF
++           Pass."
++       ::= { ospfAreaEntry 6 }
++
++
++    ospfAreaLsaCount OBJECT-TYPE
++        SYNTAX   Gauge32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The total number of link-state  advertisements
++           in  this  area's link-state database, excluding
++           AS External LSA's."
++       ::= { ospfAreaEntry 7 }
++
++
++    ospfAreaLsaCksumSum OBJECT-TYPE
++        SYNTAX   Integer32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The 32-bit unsigned sum of the link-state  ad-
++           vertisements'  LS  checksums  contained in this
++           area's link-state database.  This sum  excludes
++           external (LS type 5) link-state advertisements.
++           The sum can be used to determine if  there  has
++           been  a  change  in a router's link state data-
++           base, and to compare the link-state database of
++           two routers."
++       DEFVAL   { 0 }
++       ::= { ospfAreaEntry 8 }
++
++    ospfAreaSummary OBJECT-TYPE
++        SYNTAX   INTEGER    {
++                    noAreaSummary (1),
++                    sendAreaSummary (2)
++                  }
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The variable ospfAreaSummary controls the  im-
++           port  of  summary LSAs into stub areas.  It has
++           no effect on other areas.
++
++           If it is noAreaSummary, the router will neither
++           originate  nor  propagate summary LSAs into the
++           stub area.  It will rely entirely  on  its  de-
++           fault route.
++
++           If it is sendAreaSummary, the router will  both
++           summarize and propagate summary LSAs."
++       DEFVAL   { noAreaSummary }
++       ::= { ospfAreaEntry 9 }
++
++
++    ospfAreaStatus OBJECT-TYPE
++        SYNTAX   RowStatus
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "This variable displays the status of  the  en-
++           try.  Setting it to 'invalid' has the effect of
++           rendering it inoperative.  The internal  effect
++           (row removal) is implementation dependent."
++       ::= { ospfAreaEntry 10 }
++
++
++--  OSPF Area Default Metric Table
++
++--      The OSPF Area Default Metric Table describes the metrics
++--      that a default Area Border Router will advertise into a
++--      Stub area.
++
++
++    ospfStubAreaTable OBJECT-TYPE
++        SYNTAX   SEQUENCE OF OspfStubAreaEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "The set of metrics that will be advertised  by
++           a default Area Border Router into a stub area."
++       REFERENCE
++          "OSPF Version 2, Appendix C.2, Area Parameters"
++      ::= { ospf 3 }
++
++
++    ospfStubAreaEntry OBJECT-TYPE
++        SYNTAX   OspfStubAreaEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "The metric for a given Type  of  Service  that
++           will  be  advertised  by  a default Area Border
++           Router into a stub area."
++       REFERENCE
++          "OSPF Version 2, Appendix C.2, Area Parameters"
++      INDEX { ospfStubAreaId, ospfStubTOS }
++      ::= { ospfStubAreaTable 1 }
++
++OspfStubAreaEntry ::=
++    SEQUENCE {
++        ospfStubAreaId
++            AreaID,
++        ospfStubTOS
++            TOSType,
++        ospfStubMetric
++            BigMetric,
++        ospfStubStatus
++            RowStatus,
++        ospfStubMetricType
++            INTEGER
++              }
++
++    ospfStubAreaId OBJECT-TYPE
++        SYNTAX   AreaID
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The 32 bit identifier for the Stub  Area.   On
++           creation,  this  can  be  derived  from the in-
++           stance."
++       ::= { ospfStubAreaEntry 1 }
++
++
++    ospfStubTOS OBJECT-TYPE
++        SYNTAX   TOSType
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The  Type  of  Service  associated  with   the
++           metric.   On creation, this can be derived from
++           the instance."
++       ::= { ospfStubAreaEntry 2 }
++
++
++    ospfStubMetric OBJECT-TYPE
++        SYNTAX   BigMetric
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The metric value applied at the indicated type
++           of  service.  By default, this equals the least
++           metric at the type of service among the  inter-
++           faces to other areas."
++       ::= { ospfStubAreaEntry 3 }
++
++
++    ospfStubStatus OBJECT-TYPE
++        SYNTAX   RowStatus
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "This variable displays the status of  the  en-
++           try.  Setting it to 'invalid' has the effect of
++           rendering it inoperative.  The internal  effect
++           (row removal) is implementation dependent."
++       ::= { ospfStubAreaEntry 4 }
++
++    ospfStubMetricType OBJECT-TYPE
++        SYNTAX   INTEGER    {
++                    ospfMetric (1),                -- OSPF Metric
++                    comparableCost (2),        -- external type 1
++                    nonComparable  (3)        -- external type 2
++                  }
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "This variable displays the type of metric  ad-
++           vertised as a default route."
++       DEFVAL   { ospfMetric }
++       ::= { ospfStubAreaEntry 5 }
++
++--  OSPF Link State Database
++
++--      The Link State Database contains the Link State
++--      Advertisements from throughout the areas that the
++--      device is attached to.
++
++
++    ospfLsdbTable OBJECT-TYPE
++        SYNTAX   SEQUENCE OF OspfLsdbEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "The OSPF Process's Link State Database."
++       REFERENCE
++          "OSPF Version 2, Section 12  Link  State  Adver-
++          tisements"
++      ::= { ospf 4 }
++
++
++    ospfLsdbEntry OBJECT-TYPE
++        SYNTAX   OspfLsdbEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "A single Link State Advertisement."
++       INDEX { ospfLsdbAreaId, ospfLsdbType,
++               ospfLsdbLsid, ospfLsdbRouterId }
++       ::= { ospfLsdbTable 1 }
++
++OspfLsdbEntry ::=
++    SEQUENCE {
++        ospfLsdbAreaId
++            AreaID,
++        ospfLsdbType
++            INTEGER,
++        ospfLsdbLsid
++            IpAddress,
++        ospfLsdbRouterId
++            RouterID,
++        ospfLsdbSequence
++            Integer32,
++        ospfLsdbAge
++            Integer32,
++        ospfLsdbChecksum
++            Integer32,
++        ospfLsdbAdvertisement
++            OCTET STRING
++              }
++    ospfLsdbAreaId OBJECT-TYPE
++        SYNTAX   AreaID
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The 32 bit identifier of the Area  from  which
++           the LSA was received."
++       REFERENCE
++          "OSPF Version 2, Appendix C.2 Area parameters"
++      ::= { ospfLsdbEntry 1 }
++
++-- External Link State Advertisements are permitted
++-- for backward compatibility, but should be displayed in
++-- the ospfExtLsdbTable rather than here.
++
++    ospfLsdbType OBJECT-TYPE
++        SYNTAX   INTEGER    {
++                    routerLink (1),
++                    networkLink (2),
++                    summaryLink (3),
++                    asSummaryLink (4),
++                    asExternalLink (5), -- but see ospfExtLsdbTable
++                    multicastLink (6),
++                    nssaExternalLink (7)
++                  }
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The type  of  the  link  state  advertisement.
++           Each  link state type has a separate advertise-
++           ment format."
++       REFERENCE
++          "OSPF Version 2, Appendix A.4.1 The  Link  State
++          Advertisement header"
++      ::= { ospfLsdbEntry 2 }
++
++    ospfLsdbLsid OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The Link State ID is an LS Type Specific field
++           containing either a Router ID or an IP Address;
++           it identifies the piece of the  routing  domain
++           that is being described by the advertisement."
++       REFERENCE
++          "OSPF Version 2, Section 12.1.4 Link State ID"
++      ::= { ospfLsdbEntry 3 }
++    ospfLsdbRouterId OBJECT-TYPE
++        SYNTAX   RouterID
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The 32 bit number that uniquely identifies the
++           originating router in the Autonomous System."
++       REFERENCE
++          "OSPF Version 2, Appendix C.1 Global parameters"
++      ::= { ospfLsdbEntry 4 }
++
++--  Note that the OSPF Sequence Number is a 32 bit signed
++--  integer.  It starts with the value '80000001'h,
++--  or -'7FFFFFFF'h, and increments until '7FFFFFFF'h
++--  Thus, a typical sequence number will be very negative.
++
++    ospfLsdbSequence OBJECT-TYPE
++        SYNTAX   Integer32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The sequence number field is a  signed  32-bit
++           integer.   It  is used to detect old and dupli-
++           cate link state advertisements.  The  space  of
++           sequence  numbers  is  linearly  ordered.   The
++           larger the sequence number the more recent  the
++           advertisement."
++       REFERENCE
++          "OSPF Version  2,  Section  12.1.6  LS  sequence
++          number"
++      ::= { ospfLsdbEntry 5 }
++
++
++    ospfLsdbAge OBJECT-TYPE
++        SYNTAX   Integer32    -- Should be 0..MaxAge
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "This field is the age of the link state adver-
++           tisement in seconds."
++       REFERENCE
++          "OSPF Version 2, Section 12.1.1 LS age"
++      ::= { ospfLsdbEntry 6 }
++
++    ospfLsdbChecksum OBJECT-TYPE
++        SYNTAX   Integer32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "This field is the  checksum  of  the  complete
++           contents  of  the  advertisement, excepting the
++           age field.  The age field is excepted  so  that
++           an   advertisement's  age  can  be  incremented
++           without updating the  checksum.   The  checksum
++           used  is  the same that is used for ISO connec-
++           tionless datagrams; it is commonly referred  to
++           as the Fletcher checksum."
++       REFERENCE
++          "OSPF Version 2, Section 12.1.7 LS checksum"
++      ::= { ospfLsdbEntry 7 }
++
++
++    ospfLsdbAdvertisement OBJECT-TYPE
++        SYNTAX   OCTET STRING (SIZE (1..65535))
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The entire Link State Advertisement, including
++           its header."
++       REFERENCE
++          "OSPF Version 2, Section 12  Link  State  Adver-
++          tisements"
++      ::= { ospfLsdbEntry 8 }
++
++
++--  Address Range Table
++
++--      The Address Range Table acts as an adjunct to the Area
++--      Table; It describes those Address Range Summaries that
++--      are configured to be propagated from an Area to reduce
++--      the amount of information about it which is known beyond
++--      its borders.
++
++    ospfAreaRangeTable OBJECT-TYPE
++        SYNTAX   SEQUENCE OF OspfAreaRangeEntry
++        MAX-ACCESS   not-accessible
++        STATUS   obsolete
++        DESCRIPTION
++           "A range if IP addresses  specified  by  an  IP
++           address/IP  network  mask  pair.   For example,
++           class B address range of X.X.X.X with a network
++           mask  of  255.255.0.0 includes all IP addresses
++           from X.X.0.0 to X.X.255.255"
++       REFERENCE
++          "OSPF Version 2, Appendix C.2  Area parameters"
++      ::= { ospf 5 }
++    ospfAreaRangeEntry OBJECT-TYPE
++        SYNTAX   OspfAreaRangeEntry
++        MAX-ACCESS   not-accessible
++        STATUS   obsolete
++        DESCRIPTION
++           "A range if IP addresses  specified  by  an  IP
++           address/IP  network  mask  pair.   For example,
++           class B address range of X.X.X.X with a network
++           mask  of  255.255.0.0 includes all IP addresses
++           from X.X.0.0 to X.X.255.255"
++       REFERENCE
++          "OSPF Version 2, Appendix C.2  Area parameters"
++      INDEX { ospfAreaRangeAreaId, ospfAreaRangeNet }
++      ::= { ospfAreaRangeTable 1 }
++
++OspfAreaRangeEntry ::=
++    SEQUENCE {
++        ospfAreaRangeAreaId
++            AreaID,
++        ospfAreaRangeNet
++            IpAddress,
++        ospfAreaRangeMask
++            IpAddress,
++        ospfAreaRangeStatus
++            RowStatus,
++        ospfAreaRangeEffect
++            INTEGER
++              }
++
++    ospfAreaRangeAreaId OBJECT-TYPE
++        SYNTAX   AreaID
++        MAX-ACCESS   read-only
++        STATUS   obsolete
++        DESCRIPTION
++           "The Area the Address  Range  is  to  be  found
++           within."
++       REFERENCE
++          "OSPF Version 2, Appendix C.2 Area parameters"
++      ::= { ospfAreaRangeEntry 1 }
++
++
++    ospfAreaRangeNet OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   obsolete
++        DESCRIPTION
++           "The IP Address of the Net or Subnet  indicated
++           by the range."
++       REFERENCE
++          "OSPF Version 2, Appendix C.2 Area parameters"
++      ::= { ospfAreaRangeEntry 2 }
++
++
++    ospfAreaRangeMask OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-create
++        STATUS   obsolete
++        DESCRIPTION
++           "The Subnet Mask that pertains to  the  Net  or
++           Subnet."
++       REFERENCE
++          "OSPF Version 2, Appendix C.2 Area parameters"
++      ::= { ospfAreaRangeEntry 3 }
++
++    ospfAreaRangeStatus OBJECT-TYPE
++        SYNTAX   RowStatus
++        MAX-ACCESS   read-create
++        STATUS   obsolete
++        DESCRIPTION
++           "This variable displays the status of  the  en-
++           try.  Setting it to 'invalid' has the effect of
++           rendering it inoperative.  The internal  effect
++           (row removal) is implementation dependent."
++       ::= { ospfAreaRangeEntry 4 }
++
++
++    ospfAreaRangeEffect OBJECT-TYPE
++        SYNTAX   INTEGER    {
++                    advertiseMatching (1),
++                    doNotAdvertiseMatching (2)
++                  }
++        MAX-ACCESS   read-create
++        STATUS   obsolete
++        DESCRIPTION
++           "Subnets subsumed by ranges either trigger  the
++           advertisement  of the indicated summary (adver-
++           tiseMatching), or result in  the  subnet's  not
++           being advertised at all outside the area."
++       DEFVAL   { advertiseMatching }
++       ::= { ospfAreaRangeEntry 5 }
++
++
++
++--  OSPF Host Table
++
++--      The Host/Metric Table indicates what hosts are directly
++--      attached to the Router, and what metrics and types of
++--      service should be advertised for them.
++
++    ospfHostTable OBJECT-TYPE
++        SYNTAX   SEQUENCE OF OspfHostEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "The list of Hosts, and their metrics, that the
++           router will advertise as host routes."
++       REFERENCE
++          "OSPF Version 2, Appendix C.6  Host route param-
++          eters"
++      ::= { ospf 6 }
++
++
++    ospfHostEntry OBJECT-TYPE
++        SYNTAX   OspfHostEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "A metric to be advertised, for a given type of
++           service, when a given host is reachable."
++       INDEX { ospfHostIpAddress, ospfHostTOS }
++       ::= { ospfHostTable 1 }
++
++OspfHostEntry ::=
++    SEQUENCE {
++        ospfHostIpAddress
++            IpAddress,
++        ospfHostTOS
++            TOSType,
++        ospfHostMetric
++            Metric,
++        ospfHostStatus
++            RowStatus,
++        ospfHostAreaID
++            AreaID
++              }
++
++    ospfHostIpAddress OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The IP Address of the Host."
++       REFERENCE
++          "OSPF Version 2, Appendix C.6 Host route parame-
++          ters"
++      ::= { ospfHostEntry 1 }
++
++
++    ospfHostTOS OBJECT-TYPE
++        SYNTAX   TOSType
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The Type of Service of the route being config-
++           ured."
++       REFERENCE
++          "OSPF Version 2, Appendix C.6 Host route parame-
++          ters"
++      ::= { ospfHostEntry 2 }
++
++
++    ospfHostMetric OBJECT-TYPE
++        SYNTAX   Metric
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The Metric to be advertised."
++       REFERENCE
++          "OSPF Version 2, Appendix C.6 Host route parame-
++          ters"
++      ::= { ospfHostEntry 3 }
++
++    ospfHostStatus OBJECT-TYPE
++        SYNTAX   RowStatus
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "This variable displays the status of  the  en-
++           try.  Setting it to 'invalid' has the effect of
++           rendering it inoperative.  The internal  effect
++           (row removal) is implementation dependent."
++       ::= { ospfHostEntry 4 }
++
++
++    ospfHostAreaID OBJECT-TYPE
++        SYNTAX   AreaID
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The Area the Host Entry is to be found within.
++           By  default, the area that a subsuming OSPF in-
++           terface is in, or 0.0.0.0"
++       REFERENCE
++          "OSPF Version 2, Appendix C.2 Area parameters"
++      ::= { ospfHostEntry 5 }
++
++
++--  OSPF Interface Table
++
++--      The OSPF Interface Table augments the ipAddrTable
++--             with OSPF specific information.
++
++    ospfIfTable OBJECT-TYPE
++        SYNTAX   SEQUENCE OF OspfIfEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "The OSPF Interface Table describes the  inter-
++           faces from the viewpoint of OSPF."
++       REFERENCE
++          "OSPF Version 2, Appendix C.3  Router  interface
++          parameters"
++      ::= { ospf 7 }
++
++
++    ospfIfEntry OBJECT-TYPE
++        SYNTAX   OspfIfEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "The OSPF Interface Entry describes one  inter-
++           face from the viewpoint of OSPF."
++       INDEX { ospfIfIpAddress, ospfAddressLessIf }
++       ::= { ospfIfTable 1 }
++
++OspfIfEntry ::=
++    SEQUENCE {
++        ospfIfIpAddress
++            IpAddress,
++        ospfAddressLessIf
++            Integer32,
++        ospfIfAreaId
++            AreaID,
++        ospfIfType
++            INTEGER,
++        ospfIfAdminStat
++            Status,
++        ospfIfRtrPriority
++            DesignatedRouterPriority,
++        ospfIfTransitDelay
++            UpToMaxAge,
++        ospfIfRetransInterval
++            UpToMaxAge,
++        ospfIfHelloInterval
++            HelloRange,
++        ospfIfRtrDeadInterval
++            PositiveInteger,
++        ospfIfPollInterval
++            PositiveInteger,
++        ospfIfState
++            INTEGER,
++        ospfIfDesignatedRouter
++            IpAddress,
++        ospfIfBackupDesignatedRouter
++            IpAddress,
++        ospfIfEvents
++            Counter32,
++        ospfIfAuthType
++            INTEGER,
++        ospfIfAuthKey
++            OCTET STRING,
++        ospfIfStatus
++            RowStatus,
++        ospfIfMulticastForwarding
++            INTEGER,
++        ospfIfDemand
++            TruthValue
++              }
++
++    ospfIfIpAddress OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The IP address of this OSPF interface."
++       ::= { ospfIfEntry 1 }
++
++    ospfAddressLessIf OBJECT-TYPE
++        SYNTAX   Integer32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "For the purpose of easing  the  instancing  of
++           addressed   and  addressless  interfaces;  This
++           variable takes the value 0 on  interfaces  with
++           IP  Addresses,  and  the corresponding value of
++           ifIndex for interfaces having no IP Address."
++       ::= { ospfIfEntry 2 }
++    ospfIfAreaId OBJECT-TYPE
++        SYNTAX   AreaID
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "A 32-bit integer uniquely identifying the area
++           to  which  the  interface  connects.   Area  ID
++           0.0.0.0 is used for the OSPF backbone."
++       DEFVAL   { '00000000'H }    -- 0.0.0.0
++       ::= { ospfIfEntry 3 }
++
++    ospfIfType OBJECT-TYPE
++        SYNTAX   INTEGER    {
++                    broadcast (1),
++                    nbma (2),
++                    pointToPoint (3),
++                    pointToMultipoint (5)
++                  }
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The OSPF interface type.
++
++           By way of a default, this field may be intuited
++           from the corresponding value of ifType.  Broad-
++           cast LANs, such as  Ethernet  and  IEEE  802.5,
++           take  the  value  'broadcast', X.25 and similar
++           technologies take the value 'nbma',  and  links
++           that  are  definitively point to point take the
++           value 'pointToPoint'."
++       ::= { ospfIfEntry 4 }
++
++
++    ospfIfAdminStat OBJECT-TYPE
++        SYNTAX   Status
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The OSPF  interface's  administrative  status.
++           The  value formed on the interface, and the in-
++           terface will be advertised as an internal route
++           to  some  area.   The  value 'disabled' denotes
++           that the interface is external to OSPF."
++       DEFVAL { enabled }
++       ::= { ospfIfEntry 5 }
++
++    ospfIfRtrPriority OBJECT-TYPE
++        SYNTAX   DesignatedRouterPriority
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The  priority  of  this  interface.   Used  in
++           multi-access  networks,  this  field is used in
++           the designated router election algorithm.   The
++           value 0 signifies that the router is not eligi-
++           ble to become the  designated  router  on  this
++           particular  network.   In the event of a tie in
++           this value, routers will use their Router ID as
++           a tie breaker."
++       DEFVAL { 1 }
++       ::= { ospfIfEntry 6 }
++
++
++    ospfIfTransitDelay OBJECT-TYPE
++        SYNTAX   UpToMaxAge
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The estimated number of seconds  it  takes  to
++           transmit  a  link state update packet over this
++           interface."
++       DEFVAL { 1 }
++       ::= { ospfIfEntry 7 }
++
++
++    ospfIfRetransInterval OBJECT-TYPE
++        SYNTAX   UpToMaxAge
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The number of seconds between  link-state  ad-
++           vertisement  retransmissions,  for  adjacencies
++           belonging to this  interface.   This  value  is
++           also used when retransmitting database descrip-
++           tion and link-state request packets."
++       DEFVAL { 5 }
++       ::= { ospfIfEntry 8 }
++
++
++    ospfIfHelloInterval OBJECT-TYPE
++        SYNTAX   HelloRange
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The length of time, in  seconds,  between  the
++           Hello  packets that the router sends on the in-
++           terface.  This value must be the same  for  all
++           routers attached to a common network."
++       DEFVAL { 10 }
++       ::= { ospfIfEntry 9 }
++
++
++    ospfIfRtrDeadInterval OBJECT-TYPE
++        SYNTAX   PositiveInteger
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The number of seconds that  a  router's  Hello
++           packets  have  not been seen before it's neigh-
++           bors declare the router down.  This  should  be
++           some  multiple  of  the  Hello  interval.  This
++           value must be the same for all routers attached
++           to a common network."
++       DEFVAL { 40 }
++       ::= { ospfIfEntry 10 }
++
++
++    ospfIfPollInterval OBJECT-TYPE
++        SYNTAX   PositiveInteger
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The larger time interval, in seconds,  between
++           the  Hello  packets  sent  to  an inactive non-
++           broadcast multi- access neighbor."
++       DEFVAL { 120 }
++       ::= { ospfIfEntry 11 }
++
++
++    ospfIfState OBJECT-TYPE
++        SYNTAX   INTEGER    {
++                    down (1),
++                    loopback (2),
++                    waiting (3),
++                    pointToPoint (4),
++                    designatedRouter (5),
++                    backupDesignatedRouter (6),
++                    otherDesignatedRouter (7)
++                  }
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The OSPF Interface State."
++       DEFVAL { down }
++       ::= { ospfIfEntry 12 }
++
++
++    ospfIfDesignatedRouter OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The IP Address of the Designated Router."
++       DEFVAL   { '00000000'H }    -- 0.0.0.0
++       ::= { ospfIfEntry 13 }
++
++
++    ospfIfBackupDesignatedRouter OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The  IP  Address  of  the  Backup   Designated
++           Router."
++       DEFVAL   { '00000000'H }    -- 0.0.0.0
++       ::= { ospfIfEntry 14 }
++
++    ospfIfEvents OBJECT-TYPE
++        SYNTAX   Counter32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The number of times this  OSPF  interface  has
++           changed its state, or an error has occurred."
++       ::= { ospfIfEntry 15 }
++
++
++    ospfIfAuthKey OBJECT-TYPE
++        SYNTAX   OCTET STRING (SIZE (0..256))
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The Authentication Key.  If the Area's Author-
++           ization  Type  is  simplePassword,  and the key
++           length is shorter than 8 octets, the agent will
++           left adjust and zero fill to 8 octets.
++
++           Note that unauthenticated  interfaces  need  no
++           authentication key, and simple password authen-
++           tication cannot use a key of more  than  8  oc-
++           tets.  Larger keys are useful only with authen-
++           tication mechanisms not specified in this docu-
++           ment.
++
++           When read, ospfIfAuthKey always returns an  Oc-
++           tet String of length zero."
++       REFERENCE
++          "OSPF Version 2, Section 9  The  Interface  Data
++          Structure"
++      DEFVAL   { '0000000000000000'H }    -- 0.0.0.0.0.0.0.0
++      ::= { ospfIfEntry 16 }
++
++    ospfIfStatus OBJECT-TYPE
++        SYNTAX   RowStatus
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "This variable displays the status of  the  en-
++           try.  Setting it to 'invalid' has the effect of
++           rendering it inoperative.  The internal  effect
++           (row removal) is implementation dependent."
++       ::= { ospfIfEntry 17 }
++
++
++    ospfIfMulticastForwarding OBJECT-TYPE
++        SYNTAX   INTEGER    {
++                            blocked (1),        -- no multicast forwarding
++                            multicast (2),        -- using multicast address
++                            unicast (3)        -- to each OSPF neighbor
++                  }
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The way multicasts should  forwarded  on  this
++           interface;  not  forwarded,  forwarded  as data
++           link multicasts, or forwarded as data link uni-
++           casts.   Data link multicasting is not meaning-
++           ful on point to point and NBMA interfaces,  and
++           setting ospfMulticastForwarding to 0 effective-
++           ly disables all multicast forwarding."
++       DEFVAL { blocked }
++       ::= { ospfIfEntry 18 }
++
++
++    ospfIfDemand OBJECT-TYPE
++        SYNTAX   TruthValue
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "Indicates whether Demand OSPF procedures (hel-
++           lo supression to FULL neighbors and setting the
++           DoNotAge flag on proogated LSAs) should be per-
++           formed on this interface."
++       DEFVAL { false }
++       ::= { ospfIfEntry 19 }
++
++
++    ospfIfAuthType OBJECT-TYPE
++        SYNTAX   INTEGER (0..255)
++                    -- none (0),
++                    -- simplePassword (1)
++                    -- md5 (2)
++                    -- reserved for specification by IANA (> 2)
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The authentication type specified for  an  in-
++           terface.   Additional  authentication types may
++           be assigned locally."
++       REFERENCE
++          "OSPF Version 2, Appendix E Authentication"
++      DEFVAL { 0 }        -- no authentication, by default
++      ::= { ospfIfEntry 20 }
++
++
++--  OSPF Interface Metric Table
++
++--      The Metric Table describes the metrics to be advertised
++--      for a specified interface at the various types of service.
++--      As such, this table is an adjunct of the OSPF Interface
++--      Table.
++
++-- Types of service, as defined by RFC 791, have the ability
++-- to request low delay, high bandwidth, or reliable linkage.
++
++-- For the purposes of this specification, the measure of
++-- bandwidth
++
++--      Metric = 10^8 / ifSpeed
++
++-- is the default value.  For multiple link interfaces, note
++-- that ifSpeed is the sum of the individual link speeds.
++-- This yields a number having the following typical values:
++
++--      Network Type/bit rate   Metric
++
++--      >= 100 MBPS                 1
++--      Ethernet/802.3             10
++--      E1                         48
++--      T1 (ESF)                   65
++--       64 KBPS                 1562
++--       56 KBPS                 1785
++--       19.2 KBPS               5208
++--        9.6 KBPS              10416
++
++-- Routes that are not specified use the default (TOS 0) metric
++
++    ospfIfMetricTable OBJECT-TYPE
++        SYNTAX   SEQUENCE OF OspfIfMetricEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "The TOS metrics for  a  non-virtual  interface
++           identified by the interface index."
++       REFERENCE
++          "OSPF Version 2, Appendix C.3  Router  interface
++          parameters"
++      ::= { ospf 8 }
++
++    ospfIfMetricEntry OBJECT-TYPE
++        SYNTAX   OspfIfMetricEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "A particular TOS metric for a non-virtual  in-
++           terface identified by the interface index."
++       REFERENCE
++          "OSPF Version 2, Appendix C.3  Router  interface
++          parameters"
++      INDEX { ospfIfMetricIpAddress,
++  ospfIfMetricAddressLessIf,
++  ospfIfMetricTOS }
++      ::= { ospfIfMetricTable 1 }
++
++OspfIfMetricEntry ::=
++    SEQUENCE {
++        ospfIfMetricIpAddress
++            IpAddress,
++        ospfIfMetricAddressLessIf
++            Integer32,
++        ospfIfMetricTOS
++            TOSType,
++        ospfIfMetricValue
++            Metric,
++        ospfIfMetricStatus
++            RowStatus
++              }
++
++    ospfIfMetricIpAddress OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The IP address of this OSPF interface.  On row
++           creation,  this  can  be  derived  from the in-
++           stance."
++       ::= { ospfIfMetricEntry 1 }
++
++    ospfIfMetricAddressLessIf OBJECT-TYPE
++        SYNTAX   Integer32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "For the purpose of easing  the  instancing  of
++           addressed   and  addressless  interfaces;  This
++           variable takes the value 0 on  interfaces  with
++           IP  Addresses, and the value of ifIndex for in-
++           terfaces having no IP Address.   On  row  crea-
++           tion, this can be derived from the instance."
++       ::= { ospfIfMetricEntry 2 }
++
++
++    ospfIfMetricTOS OBJECT-TYPE
++        SYNTAX   TOSType
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The type of service metric  being  referenced.
++           On  row  creation, this can be derived from the
++           instance."
++       ::= { ospfIfMetricEntry 3 }
++
++
++    ospfIfMetricValue OBJECT-TYPE
++        SYNTAX   Metric
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The metric of using this type  of  service  on
++           this interface.  The default value of the TOS 0
++           Metric is 10^8 / ifSpeed."
++       ::= { ospfIfMetricEntry 4 }
++
++    ospfIfMetricStatus OBJECT-TYPE
++        SYNTAX   RowStatus
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "This variable displays the status of  the  en-
++           try.  Setting it to 'invalid' has the effect of
++           rendering it inoperative.  The internal  effect
++           (row removal) is implementation dependent."
++       ::= { ospfIfMetricEntry 5 }
++
++
++--  OSPF Virtual Interface Table
++
++--      The Virtual Interface Table describes the virtual
++--      links that the OSPF Process is configured to
++--      carry on.
++
++    ospfVirtIfTable OBJECT-TYPE
++        SYNTAX   SEQUENCE OF OspfVirtIfEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "Information about this router's virtual inter-
++           faces."
++       REFERENCE
++          "OSPF Version  2,  Appendix  C.4   Virtual  link
++          parameters"
++      ::= { ospf 9 }
++
++
++    ospfVirtIfEntry OBJECT-TYPE
++        SYNTAX   OspfVirtIfEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "Information about a single Virtual Interface."
++       INDEX { ospfVirtIfAreaId, ospfVirtIfNeighbor }
++       ::= { ospfVirtIfTable 1 }
++
++OspfVirtIfEntry ::=
++    SEQUENCE {
++        ospfVirtIfAreaId
++            AreaID,
++        ospfVirtIfNeighbor
++            RouterID,
++        ospfVirtIfTransitDelay
++            UpToMaxAge,
++        ospfVirtIfRetransInterval
++            UpToMaxAge,
++        ospfVirtIfHelloInterval
++            HelloRange,
++        ospfVirtIfRtrDeadInterval
++            PositiveInteger,
++        ospfVirtIfState
++            INTEGER,
++        ospfVirtIfEvents
++            Counter32,
++        ospfVirtIfAuthType
++            INTEGER,
++        ospfVirtIfAuthKey
++            OCTET STRING,
++        ospfVirtIfStatus
++            RowStatus
++              }
++
++    ospfVirtIfAreaId OBJECT-TYPE
++        SYNTAX   AreaID
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The  Transit  Area  that  the   Virtual   Link
++           traverses.  By definition, this is not 0.0.0.0"
++       ::= { ospfVirtIfEntry 1 }
++
++
++    ospfVirtIfNeighbor OBJECT-TYPE
++        SYNTAX   RouterID
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The Router ID of the Virtual Neighbor."
++       ::= { ospfVirtIfEntry 2 }
++
++
++    ospfVirtIfTransitDelay OBJECT-TYPE
++        SYNTAX   UpToMaxAge
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The estimated number of seconds  it  takes  to
++           transmit  a link- state update packet over this
++           interface."
++       DEFVAL { 1 }
++       ::= { ospfVirtIfEntry 3 }
++
++
++    ospfVirtIfRetransInterval OBJECT-TYPE
++        SYNTAX   UpToMaxAge
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The number of seconds between  link-state  ad-
++           vertisement  retransmissions,  for  adjacencies
++           belonging to this  interface.   This  value  is
++           also used when retransmitting database descrip-
++           tion  and  link-state  request  packets.   This
++           value  should  be well over the expected round-
++           trip time."
++       DEFVAL { 5 }
++       ::= { ospfVirtIfEntry 4 }
++
++
++    ospfVirtIfHelloInterval OBJECT-TYPE
++        SYNTAX   HelloRange
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The length of time, in  seconds,  between  the
++           Hello  packets that the router sends on the in-
++           terface.  This value must be the same  for  the
++           virtual neighbor."
++       DEFVAL { 10 }
++       ::= { ospfVirtIfEntry 5 }
++
++
++    ospfVirtIfRtrDeadInterval OBJECT-TYPE
++        SYNTAX   PositiveInteger
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The number of seconds that  a  router's  Hello
++           packets  have  not been seen before it's neigh-
++           bors declare the router down.  This  should  be
++           some  multiple  of  the  Hello  interval.  This
++           value must be the same for the  virtual  neigh-
++           bor."
++       DEFVAL { 60 }
++       ::= { ospfVirtIfEntry 6 }
++
++
++    ospfVirtIfState OBJECT-TYPE
++        SYNTAX   INTEGER    {
++                    down (1),            -- these use the same encoding
++                    pointToPoint (4)     -- as the ospfIfTable
++                  }
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "OSPF virtual interface states."
++       DEFVAL   { down }
++       ::= { ospfVirtIfEntry 7 }
++
++
++    ospfVirtIfEvents OBJECT-TYPE
++        SYNTAX   Counter32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The number of state changes or error events on
++           this Virtual Link"
++       ::= { ospfVirtIfEntry 8 }
++
++
++    ospfVirtIfAuthKey OBJECT-TYPE
++        SYNTAX   OCTET STRING (SIZE(0..256))
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "If Authentication Type is simplePassword,  the
++           device  will left adjust and zero fill to 8 oc-
++           tets.
++
++           Note that unauthenticated  interfaces  need  no
++           authentication key, and simple password authen-
++           tication cannot use a key of more  than  8  oc-
++           tets.  Larger keys are useful only with authen-
++           tication mechanisms not specified in this docu-
++           ment.
++
++           When  read,  ospfVifAuthKey  always  returns  a
++           string of length zero."
++       REFERENCE
++          "OSPF Version 2, Section 9  The  Interface  Data
++          Structure"
++      DEFVAL   { '0000000000000000'H }    -- 0.0.0.0.0.0.0.0
++      ::= { ospfVirtIfEntry 9 }
++
++
++    ospfVirtIfStatus OBJECT-TYPE
++        SYNTAX   RowStatus
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "This variable displays the status of  the  en-
++           try.  Setting it to 'invalid' has the effect of
++           rendering it inoperative.  The internal  effect
++           (row removal) is implementation dependent."
++       ::= { ospfVirtIfEntry 10 }
++
++
++    ospfVirtIfAuthType OBJECT-TYPE
++        SYNTAX   INTEGER (0..255)
++                    -- none (0),
++                    -- simplePassword (1)
++                    -- md5 (2)
++                    -- reserved for specification by IANA (> 2)
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The authentication type specified for a virtu-
++           al  interface.  Additional authentication types
++           may be assigned locally."
++       REFERENCE
++          "OSPF Version 2, Appendix E Authentication"
++      DEFVAL { 0 }        -- no authentication, by default
++      ::= { ospfVirtIfEntry 11 }
++
++
++--  OSPF Neighbor Table
++
++--      The OSPF Neighbor Table describes all neighbors in
++--      the locality of the subject router.
++
++    ospfNbrTable OBJECT-TYPE
++        SYNTAX   SEQUENCE OF OspfNbrEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "A table of non-virtual neighbor information."
++       REFERENCE
++          "OSPF Version 2, Section 10  The  Neighbor  Data
++          Structure"
++      ::= { ospf 10 }
++
++
++    ospfNbrEntry OBJECT-TYPE
++        SYNTAX   OspfNbrEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "The information regarding a single neighbor."
++       REFERENCE
++          "OSPF Version 2, Section 10  The  Neighbor  Data
++          Structure"
++      INDEX { ospfNbrIpAddr, ospfNbrAddressLessIndex }
++      ::= { ospfNbrTable 1 }
++
++OspfNbrEntry ::=
++    SEQUENCE {
++        ospfNbrIpAddr
++            IpAddress,
++        ospfNbrAddressLessIndex
++            InterfaceIndex,
++        ospfNbrRtrId
++            RouterID,
++        ospfNbrOptions
++            Integer32,
++        ospfNbrPriority
++            DesignatedRouterPriority,
++        ospfNbrState
++            INTEGER,
++        ospfNbrEvents
++            Counter32,
++        ospfNbrLsRetransQLen
++            Gauge32,
++        ospfNbmaNbrStatus
++            RowStatus,
++        ospfNbmaNbrPermanence
++            INTEGER,
++        ospfNbrHelloSuppressed
++            TruthValue
++              }
++
++    ospfNbrIpAddr OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The IP address this neighbor is using  in  its
++           IP  Source  Address.  Note that, on addressless
++           links, this will not be 0.0.0.0,  but  the  ad-
++           dress of another of the neighbor's interfaces."
++       ::= { ospfNbrEntry 1 }
++
++
++    ospfNbrAddressLessIndex OBJECT-TYPE
++        SYNTAX   InterfaceIndex
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "On an interface having an  IP  Address,  zero.
++           On  addressless  interfaces,  the corresponding
++           value of ifIndex in the Internet Standard  MIB.
++           On  row  creation, this can be derived from the
++           instance."
++       ::= { ospfNbrEntry 2 }
++
++
++    ospfNbrRtrId OBJECT-TYPE
++        SYNTAX   RouterID
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "A 32-bit integer (represented as a type  IpAd-
++           dress)  uniquely  identifying  the  neighboring
++           router in the Autonomous System."
++       DEFVAL   { '00000000'H }    -- 0.0.0.0
++       ::= { ospfNbrEntry 3 }
++
++
++    ospfNbrOptions OBJECT-TYPE
++        SYNTAX   Integer32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "A Bit Mask corresponding to the neighbor's op-
++           tions field.
++
++           Bit 0, if set, indicates that the  system  will
++           operate  on  Type of Service metrics other than
++           TOS 0.  If zero, the neighbor will  ignore  all
++           metrics except the TOS 0 metric.
++
++           Bit 1, if set, indicates  that  the  associated
++           area  accepts and operates on external informa-
++           tion; if zero, it is a stub area.
++
++           Bit 2, if set, indicates that the system is ca-
++           pable  of routing IP Multicast datagrams; i.e.,
++           that it implements the Multicast Extensions  to
++           OSPF.
++
++           Bit 3, if set, indicates  that  the  associated
++           area  is  an  NSSA.  These areas are capable of
++           carrying type 7 external advertisements,  which
++           are  translated into type 5 external advertise-
++           ments at NSSA borders."
++       REFERENCE
++          "OSPF Version 2, Section 12.1.2 Options"
++      DEFVAL { 0 }
++      ::= { ospfNbrEntry 4 }
++
++
++    ospfNbrPriority OBJECT-TYPE
++        SYNTAX   DesignatedRouterPriority
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The priority of this neighbor in the designat-
++           ed router election algorithm.  The value 0 sig-
++           nifies that the neighbor is not eligible to be-
++           come  the  designated router on this particular
++           network."
++       DEFVAL { 1 }
++       ::= { ospfNbrEntry 5 }
++
++
++    ospfNbrState OBJECT-TYPE
++        SYNTAX   INTEGER    {
++                    down (1),
++                    attempt (2),
++                    init (3),
++                    twoWay (4),
++                    exchangeStart (5),
++                    exchange (6),
++                    loading (7),
++                    full (8)
++                  }
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The State of the relationship with this Neigh-
++           bor."
++       REFERENCE
++          "OSPF Version 2, Section 10.1 Neighbor States"
++      DEFVAL   { down }
++      ::= { ospfNbrEntry 6 }
++
++
++    ospfNbrEvents OBJECT-TYPE
++        SYNTAX   Counter32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The number of times this neighbor relationship
++           has changed state, or an error has occurred."
++       ::= { ospfNbrEntry 7 }
++
++
++    ospfNbrLsRetransQLen OBJECT-TYPE
++        SYNTAX   Gauge32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The  current  length  of  the   retransmission
++           queue."
++       ::= { ospfNbrEntry 8 }
++
++
++    ospfNbmaNbrStatus OBJECT-TYPE
++        SYNTAX   RowStatus
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "This variable displays the status of  the  en-
++           try.  Setting it to 'invalid' has the effect of
++           rendering it inoperative.  The internal  effect
++           (row removal) is implementation dependent."
++       ::= { ospfNbrEntry 9 }
++
++
++    ospfNbmaNbrPermanence OBJECT-TYPE
++        SYNTAX   INTEGER    {
++                    dynamic (1),        -- learned through protocol
++                    permanent (2)       -- configured address
++                  }
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "This variable displays the status of  the  en-
++           try.   'dynamic'  and  'permanent' refer to how
++           the neighbor became known."
++       DEFVAL { permanent }
++       ::= { ospfNbrEntry 10 }
++
++
++    ospfNbrHelloSuppressed OBJECT-TYPE
++        SYNTAX   TruthValue
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "Indicates whether Hellos are being  suppressed
++           to the neighbor"
++       ::= { ospfNbrEntry 11 }
++
++
++--  OSPF Virtual Neighbor Table
++
++--      This table describes all virtual neighbors.
++--      Since Virtual Links are configured in the
++--      virtual interface table, this table is read-only.
++
++    ospfVirtNbrTable OBJECT-TYPE
++        SYNTAX   SEQUENCE OF OspfVirtNbrEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "A table of virtual neighbor information."
++       REFERENCE
++          "OSPF Version 2, Section 15  Virtual Links"
++      ::= { ospf 11 }
++
++
++    ospfVirtNbrEntry OBJECT-TYPE
++        SYNTAX   OspfVirtNbrEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "Virtual neighbor information."
++       INDEX { ospfVirtNbrArea, ospfVirtNbrRtrId }
++       ::= { ospfVirtNbrTable 1 }
++
++OspfVirtNbrEntry ::=
++    SEQUENCE {
++        ospfVirtNbrArea
++            AreaID,
++        ospfVirtNbrRtrId
++            RouterID,
++        ospfVirtNbrIpAddr
++            IpAddress,
++        ospfVirtNbrOptions
++            Integer32,
++        ospfVirtNbrState
++            INTEGER,
++        ospfVirtNbrEvents
++            Counter32,
++        ospfVirtNbrLsRetransQLen
++            Gauge32,
++        ospfVirtNbrHelloSuppressed
++                TruthValue
++              }
++
++    ospfVirtNbrArea OBJECT-TYPE
++        SYNTAX   AreaID
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The Transit Area Identifier."
++       ::= { ospfVirtNbrEntry 1 }
++
++
++    ospfVirtNbrRtrId OBJECT-TYPE
++        SYNTAX   RouterID
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "A  32-bit  integer  uniquely  identifying  the
++           neighboring router in the Autonomous System."
++       ::= { ospfVirtNbrEntry 2 }
++
++
++    ospfVirtNbrIpAddr OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The IP address this Virtual  Neighbor  is  us-
++           ing."
++       ::= { ospfVirtNbrEntry 3 }
++
++
++    ospfVirtNbrOptions OBJECT-TYPE
++        SYNTAX   Integer32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "A Bit Mask corresponding to the neighbor's op-
++           tions field.
++
++           Bit 1, if set, indicates that the  system  will
++           operate  on  Type of Service metrics other than
++           TOS 0.  If zero, the neighbor will  ignore  all
++           metrics except the TOS 0 metric.
++
++           Bit 2, if set, indicates  that  the  system  is
++           Network  Multicast  capable; ie, that it imple-
++           ments OSPF Multicast Routing."
++       ::= { ospfVirtNbrEntry 4 }
++    ospfVirtNbrState OBJECT-TYPE
++        SYNTAX   INTEGER    {
++                    down (1),
++                    attempt (2),
++                    init (3),
++                    twoWay (4),
++                    exchangeStart (5),
++                    exchange (6),
++                    loading (7),
++                    full (8)
++                  }
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The state of the  Virtual  Neighbor  Relation-
++           ship."
++       ::= { ospfVirtNbrEntry 5 }
++
++
++    ospfVirtNbrEvents OBJECT-TYPE
++        SYNTAX   Counter32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The number of  times  this  virtual  link  has
++           changed its state, or an error has occurred."
++       ::= { ospfVirtNbrEntry 6 }
++
++
++    ospfVirtNbrLsRetransQLen OBJECT-TYPE
++        SYNTAX   Gauge32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The  current  length  of  the   retransmission
++           queue."
++       ::= { ospfVirtNbrEntry 7 }
++
++
++    ospfVirtNbrHelloSuppressed OBJECT-TYPE
++        SYNTAX   TruthValue
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "Indicates whether Hellos are being  suppressed
++           to the neighbor"
++       ::= { ospfVirtNbrEntry 8 }
++
++--  OSPF Link State Database, External
++
++--      The Link State Database contains the Link State
++--      Advertisements from throughout the areas that the
++--      device is attached to.
++
++--             This table is identical to the OSPF LSDB Table in
++--      format, but contains only External Link State
++--             Advertisements.  The purpose is to allow external
++--      LSAs to be displayed once for the router rather
++--      than once in each non-stub area.
++
++    ospfExtLsdbTable OBJECT-TYPE
++        SYNTAX   SEQUENCE OF OspfExtLsdbEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "The OSPF Process's Links State Database."
++       REFERENCE
++          "OSPF Version 2, Section 12  Link  State  Adver-
++          tisements"
++      ::= { ospf 12 }
++
++
++    ospfExtLsdbEntry OBJECT-TYPE
++        SYNTAX   OspfExtLsdbEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "A single Link State Advertisement."
++       INDEX { ospfExtLsdbType, ospfExtLsdbLsid, ospfExtLsdbRouterId }
++       ::= { ospfExtLsdbTable 1 }
++
++OspfExtLsdbEntry ::=
++    SEQUENCE {
++        ospfExtLsdbType
++            INTEGER,
++        ospfExtLsdbLsid
++            IpAddress,
++        ospfExtLsdbRouterId
++            RouterID,
++        ospfExtLsdbSequence
++            Integer32,
++        ospfExtLsdbAge
++            Integer32,
++        ospfExtLsdbChecksum
++            Integer32,
++        ospfExtLsdbAdvertisement
++            OCTET STRING
++              }
++
++    ospfExtLsdbType OBJECT-TYPE
++        SYNTAX   INTEGER    {
++                    asExternalLink (5)
++                  }
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The type  of  the  link  state  advertisement.
++           Each  link state type has a separate advertise-
++           ment format."
++       REFERENCE
++          "OSPF Version 2, Appendix A.4.1 The  Link  State
++          Advertisement header"
++      ::= { ospfExtLsdbEntry 1 }
++
++
++    ospfExtLsdbLsid OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The Link State ID is an LS Type Specific field
++           containing either a Router ID or an IP Address;
++           it identifies the piece of the  routing  domain
++           that is being described by the advertisement."
++       REFERENCE
++          "OSPF Version 2, Section 12.1.4 Link State ID"
++      ::= { ospfExtLsdbEntry 2 }
++
++
++    ospfExtLsdbRouterId OBJECT-TYPE
++        SYNTAX   RouterID
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The 32 bit number that uniquely identifies the
++           originating router in the Autonomous System."
++       REFERENCE
++          "OSPF Version 2, Appendix C.1 Global parameters"
++      ::= { ospfExtLsdbEntry 3 }
++
++--  Note that the OSPF Sequence Number is a 32 bit signed
++--  integer.  It starts with the value '80000001'h,
++--  or -'7FFFFFFF'h, and increments until '7FFFFFFF'h
++--  Thus, a typical sequence number will be very negative.
++    ospfExtLsdbSequence OBJECT-TYPE
++        SYNTAX   Integer32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The sequence number field is a  signed  32-bit
++           integer.   It  is used to detect old and dupli-
++           cate link state advertisements.  The  space  of
++           sequence  numbers  is  linearly  ordered.   The
++           larger the sequence number the more recent  the
++           advertisement."
++       REFERENCE
++          "OSPF Version  2,  Section  12.1.6  LS  sequence
++          number"
++      ::= { ospfExtLsdbEntry 4 }
++
++
++    ospfExtLsdbAge OBJECT-TYPE
++        SYNTAX   Integer32    -- Should be 0..MaxAge
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "This field is the age of the link state adver-
++           tisement in seconds."
++       REFERENCE
++          "OSPF Version 2, Section 12.1.1 LS age"
++      ::= { ospfExtLsdbEntry 5 }
++
++
++    ospfExtLsdbChecksum OBJECT-TYPE
++        SYNTAX   Integer32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "This field is the  checksum  of  the  complete
++           contents  of  the  advertisement, excepting the
++           age field.  The age field is excepted  so  that
++           an   advertisement's  age  can  be  incremented
++           without updating the  checksum.   The  checksum
++           used  is  the same that is used for ISO connec-
++           tionless datagrams; it is commonly referred  to
++           as the Fletcher checksum."
++       REFERENCE
++          "OSPF Version 2, Section 12.1.7 LS checksum"
++      ::= { ospfExtLsdbEntry 6 }
++
++
++    ospfExtLsdbAdvertisement OBJECT-TYPE
++        SYNTAX   OCTET STRING (SIZE(36))
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The entire Link State Advertisement, including
++           its header."
++       REFERENCE
++          "OSPF Version 2, Section 12  Link  State  Adver-
++          tisements"
++      ::= { ospfExtLsdbEntry 7 }
++
++
++--  OSPF Use of the CIDR Route Table
++
++ospfRouteGroup           OBJECT IDENTIFIER ::= { ospf 13 }
++
++-- The IP Forwarding Table defines a number of objects for use by
++-- the routing protocol to externalize its information.  Most of
++-- the variables (ipForwardDest, ipForwardMask, ipForwardPolicy,
++-- ipForwardNextHop, ipForwardIfIndex, ipForwardType,
++-- ipForwardProto, ipForwardAge, and ipForwardNextHopAS) are
++-- defined there.
++
++-- Those that leave some discretion are defined here.
++
++-- ipCidrRouteProto is, of course, ospf (13).
++
++-- ipCidrRouteAge is the time since the route was first calculated,
++-- as opposed to the time since the last SPF run.
++
++-- ipCidrRouteInfo is an OBJECT IDENTIFIER for use by the routing
++-- protocol.  The following values shall be found there depending
++-- on the way the route was calculated.
++
++ospfIntraArea      OBJECT IDENTIFIER ::= { ospfRouteGroup 1 }
++ospfInterArea      OBJECT IDENTIFIER ::= { ospfRouteGroup 2 }
++ospfExternalType1  OBJECT IDENTIFIER ::= { ospfRouteGroup 3 }
++ospfExternalType2  OBJECT IDENTIFIER ::= { ospfRouteGroup 4 }
++
++-- ipCidrRouteMetric1 is, by definition, the primary routing
++-- metric.  Therefore, it should be the metric that route
++-- selection is based on.  For intra-area and inter-area routes,
++-- it is an OSPF metric.  For External Type 1 (comparable value)
++-- routes, it is an OSPF metric plus the External Metric.  For
++-- external Type 2 (non-comparable value) routes, it is the
++-- external metric.
++
++-- ipCidrRouteMetric2 is, by definition, a secondary routing
++-- metric.  Therefore, it should be the metric that breaks a tie
++-- among routes having equal metric1 values and the same
++-- calculation rule.  For intra-area, inter-area routes, and
++-- External Type 1 (comparable value) routes, it is unused.  For
++-- external Type 2 (non-comparable value) routes, it is the metric
++-- to the AS border router.
++
++-- ipCidrRouteMetric3, ipCidrRouteMetric4, and ipCidrRouteMetric5 are
++-- unused.
++
++--
++--      The OSPF Area Aggregate Table
++--
++--      This table replaces the OSPF Area Summary Table, being an
++--      extension of that for CIDR routers.
++
++    ospfAreaAggregateTable OBJECT-TYPE
++        SYNTAX   SEQUENCE OF OspfAreaAggregateEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "A range of IP addresses  specified  by  an  IP
++           address/IP  network  mask  pair.   For example,
++           class B address range of X.X.X.X with a network
++           mask  of  255.255.0.0 includes all IP addresses
++           from X.X.0.0  to  X.X.255.255.   Note  that  if
++           ranges  are configured such that one range sub-
++           sumes  another  range  (e.g.,   10.0.0.0   mask
++           255.0.0.0  and  10.1.0.0 mask 255.255.0.0), the
++           most specific match is the preferred one."
++       REFERENCE
++          "OSPF Version 2, Appendix C.2  Area parameters"
++      ::= { ospf 14 }
++
++
++    ospfAreaAggregateEntry OBJECT-TYPE
++        SYNTAX   OspfAreaAggregateEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "A range of IP addresses  specified  by  an  IP
++           address/IP  network  mask  pair.   For example,
++           class B address range of X.X.X.X with a network
++           mask  of  255.255.0.0 includes all IP addresses
++           from X.X.0.0  to  X.X.255.255.   Note  that  if
++           ranges are range configured such that one range
++           subsumes another  range  (e.g.,  10.0.0.0  mask
++           255.0.0.0  and  10.1.0.0 mask 255.255.0.0), the
++           most specific match is the preferred one."
++       REFERENCE
++          "OSPF Version 2, Appendix C.2  Area parameters"
++      INDEX { ospfAreaAggregateAreaID, ospfAreaAggregateLsdbType,
++              ospfAreaAggregateNet, ospfAreaAggregateMask }
++      ::= { ospfAreaAggregateTable 1 }
++
++
++OspfAreaAggregateEntry ::=
++    SEQUENCE {
++        ospfAreaAggregateAreaID
++            AreaID,
++        ospfAreaAggregateLsdbType
++            INTEGER,
++        ospfAreaAggregateNet
++            IpAddress,
++        ospfAreaAggregateMask
++            IpAddress,
++        ospfAreaAggregateStatus
++            RowStatus,
++        ospfAreaAggregateEffect
++            INTEGER
++              }
++
++    ospfAreaAggregateAreaID OBJECT-TYPE
++        SYNTAX   AreaID
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The Area the Address Aggregate is to be  found
++           within."
++       REFERENCE
++          "OSPF Version 2, Appendix C.2 Area parameters"
++      ::= { ospfAreaAggregateEntry 1 }
++
++
++    ospfAreaAggregateLsdbType OBJECT-TYPE
++        SYNTAX   INTEGER    {
++                    summaryLink (3),
++                    nssaExternalLink (7)
++                  }
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The type of the Address Aggregate.  This field
++           specifies  the  Lsdb type that this Address Ag-
++           gregate applies to."
++       REFERENCE
++          "OSPF Version 2, Appendix A.4.1 The  Link  State
++          Advertisement header"
++      ::= { ospfAreaAggregateEntry 2 }
++
++
++    ospfAreaAggregateNet OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The IP Address of the Net or Subnet  indicated
++           by the range."
++       REFERENCE
++          "OSPF Version 2, Appendix C.2 Area parameters"
++      ::= { ospfAreaAggregateEntry 3 }
++
++
++    ospfAreaAggregateMask OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The Subnet Mask that pertains to  the  Net  or
++           Subnet."
++       REFERENCE
++          "OSPF Version 2, Appendix C.2 Area parameters"
++      ::= { ospfAreaAggregateEntry 4 }
++
++
++    ospfAreaAggregateStatus OBJECT-TYPE
++        SYNTAX   RowStatus
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "This variable displays the status of  the  en-
++           try.  Setting it to 'invalid' has the effect of
++           rendering it inoperative.  The internal  effect
++           (row removal) is implementation dependent."
++       ::= { ospfAreaAggregateEntry 5 }
++
++
++    ospfAreaAggregateEffect OBJECT-TYPE
++        SYNTAX   INTEGER    {
++                    advertiseMatching (1),
++                    doNotAdvertiseMatching (2)
++                  }
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "Subnets subsumed by ranges either trigger  the
++           advertisement  of  the indicated aggregate (ad-
++           vertiseMatching), or result in the subnet's not
++           being advertised at all outside the area."
++       DEFVAL   { advertiseMatching }
++       ::= { ospfAreaAggregateEntry 6 }
++
++
++-- conformance information
++
++ospfConformance OBJECT IDENTIFIER ::= { ospf 15 }
++
++ospfGroups      OBJECT IDENTIFIER ::= { ospfConformance 1 }
++ospfCompliances OBJECT IDENTIFIER ::= { ospfConformance 2 }
++
++-- compliance statements
++
++    ospfCompliance MODULE-COMPLIANCE
++        STATUS  current
++        DESCRIPTION
++           "The compliance statement "
++       MODULE  -- this module
++       MANDATORY-GROUPS {
++                    ospfBasicGroup,
++                    ospfAreaGroup,
++                    ospfStubAreaGroup,
++                    ospfIfGroup,
++                    ospfIfMetricGroup,
++                    ospfVirtIfGroup,
++                    ospfNbrGroup,
++                    ospfVirtNbrGroup,
++                    ospfAreaAggregateGroup
++           }
++       ::= { ospfCompliances 1 }
++
++
++-- units of conformance
++
++    ospfBasicGroup    OBJECT-GROUP
++        OBJECTS {
++                    ospfRouterId,
++                    ospfAdminStat,
++                    ospfVersionNumber,
++                    ospfAreaBdrRtrStatus,
++                    ospfASBdrRtrStatus,
++                    ospfExternLsaCount,
++                    ospfExternLsaCksumSum,
++                    ospfTOSSupport,
++                    ospfOriginateNewLsas,
++                    ospfRxNewLsas,
++                    ospfExtLsdbLimit,
++                    ospfMulticastExtensions,
++                    ospfExitOverflowInterval,
++                    ospfDemandExtensions
++        }
++        STATUS  current
++        DESCRIPTION
++           "These objects are required for OSPF systems."
++       ::= { ospfGroups 1 }
++
++
++    ospfAreaGroup    OBJECT-GROUP
++        OBJECTS {
++                    ospfAreaId,
++                    ospfImportAsExtern,
++                    ospfSpfRuns,
++                    ospfAreaBdrRtrCount,
++                    ospfAsBdrRtrCount,
++                    ospfAreaLsaCount,
++                    ospfAreaLsaCksumSum,
++                    ospfAreaSummary,
++                    ospfAreaStatus
++        }
++        STATUS  current
++        DESCRIPTION
++           "These objects are required  for  OSPF  systems
++           supporting areas."
++       ::= { ospfGroups 2 }
++
++
++    ospfStubAreaGroup    OBJECT-GROUP
++        OBJECTS {
++                    ospfStubAreaId,
++                    ospfStubTOS,
++                    ospfStubMetric,
++                    ospfStubStatus,
++                    ospfStubMetricType
++        }
++        STATUS  current
++        DESCRIPTION
++           "These objects are required  for  OSPF  systems
++           supporting stub areas."
++       ::= { ospfGroups 3 }
++
++
++    ospfLsdbGroup    OBJECT-GROUP
++        OBJECTS {
++                    ospfLsdbAreaId,
++                    ospfLsdbType,
++                    ospfLsdbLsid,
++                    ospfLsdbRouterId,
++                    ospfLsdbSequence,
++                    ospfLsdbAge,
++                    ospfLsdbChecksum,
++                    ospfLsdbAdvertisement
++        }
++        STATUS  current
++        DESCRIPTION
++           "These objects are required  for  OSPF  systems
++           that display their link state database."
++       ::= { ospfGroups 4 }
++
++
++    ospfAreaRangeGroup    OBJECT-GROUP
++        OBJECTS {
++                    ospfAreaRangeAreaId,
++                    ospfAreaRangeNet,
++                    ospfAreaRangeMask,
++                    ospfAreaRangeStatus,
++                    ospfAreaRangeEffect
++        }
++        STATUS  obsolete
++        DESCRIPTION
++           "These objects are required for  non-CIDR  OSPF
++           systems that support multiple areas."
++       ::= { ospfGroups 5 }
++
++
++    ospfHostGroup    OBJECT-GROUP
++        OBJECTS {
++                    ospfHostIpAddress,
++                    ospfHostTOS,
++                    ospfHostMetric,
++                    ospfHostStatus,
++                    ospfHostAreaID
++        }
++        STATUS  current
++        DESCRIPTION
++           "These objects are required  for  OSPF  systems
++           that support attached hosts."
++       ::= { ospfGroups 6 }
++
++
++    ospfIfGroup    OBJECT-GROUP
++        OBJECTS {
++                    ospfIfIpAddress,
++                    ospfAddressLessIf,
++                    ospfIfAreaId,
++                    ospfIfType,
++                    ospfIfAdminStat,
++                    ospfIfRtrPriority,
++                    ospfIfTransitDelay,
++                    ospfIfRetransInterval,
++                    ospfIfHelloInterval,
++                    ospfIfRtrDeadInterval,
++                    ospfIfPollInterval,
++                    ospfIfState,
++                    ospfIfDesignatedRouter,
++                    ospfIfBackupDesignatedRouter,
++                    ospfIfEvents,
++                    ospfIfAuthType,
++                    ospfIfAuthKey,
++                    ospfIfStatus,
++                    ospfIfMulticastForwarding,
++                    ospfIfDemand
++        }
++        STATUS  current
++        DESCRIPTION
++           "These objects are required for OSPF systems."
++       ::= { ospfGroups 7 }
++
++
++    ospfIfMetricGroup    OBJECT-GROUP
++        OBJECTS {
++                    ospfIfMetricIpAddress,
++                    ospfIfMetricAddressLessIf,
++                    ospfIfMetricTOS,
++                    ospfIfMetricValue,
++                    ospfIfMetricStatus
++        }
++        STATUS  current
++        DESCRIPTION
++           "These objects are required for OSPF systems."
++       ::= { ospfGroups 8 }
++
++
++    ospfVirtIfGroup    OBJECT-GROUP
++        OBJECTS {
++                    ospfVirtIfAreaId,
++                    ospfVirtIfNeighbor,
++                    ospfVirtIfTransitDelay,
++                    ospfVirtIfRetransInterval,
++                    ospfVirtIfHelloInterval,
++                    ospfVirtIfRtrDeadInterval,
++                    ospfVirtIfState,
++                    ospfVirtIfEvents,
++                    ospfVirtIfAuthType,
++                    ospfVirtIfAuthKey,
++                    ospfVirtIfStatus
++        }
++        STATUS  current
++        DESCRIPTION
++           "These objects are required for OSPF systems."
++       ::= { ospfGroups 9 }
++
++
++    ospfNbrGroup    OBJECT-GROUP
++        OBJECTS {
++                    ospfNbrIpAddr,
++                    ospfNbrAddressLessIndex,
++                    ospfNbrRtrId,
++                    ospfNbrOptions,
++                    ospfNbrPriority,
++                    ospfNbrState,
++                    ospfNbrEvents,
++                    ospfNbrLsRetransQLen,
++                    ospfNbmaNbrStatus,
++                    ospfNbmaNbrPermanence,
++                    ospfNbrHelloSuppressed
++        }
++        STATUS  current
++        DESCRIPTION
++           "These objects are required for OSPF systems."
++       ::= { ospfGroups 10 }
++
++
++    ospfVirtNbrGroup    OBJECT-GROUP
++        OBJECTS {
++                    ospfVirtNbrArea,
++                    ospfVirtNbrRtrId,
++                    ospfVirtNbrIpAddr,
++                    ospfVirtNbrOptions,
++                    ospfVirtNbrState,
++                    ospfVirtNbrEvents,
++                    ospfVirtNbrLsRetransQLen,
++                    ospfVirtNbrHelloSuppressed
++        }
++        STATUS  current
++        DESCRIPTION
++           "These objects are required for OSPF systems."
++       ::= { ospfGroups 11 }
++
++
++    ospfExtLsdbGroup    OBJECT-GROUP
++        OBJECTS {
++                    ospfExtLsdbType,
++                    ospfExtLsdbLsid,
++                    ospfExtLsdbRouterId,
++                    ospfExtLsdbSequence,
++                    ospfExtLsdbAge,
++                    ospfExtLsdbChecksum,
++                    ospfExtLsdbAdvertisement
++        }
++        STATUS  current
++        DESCRIPTION
++           "These objects are required  for  OSPF  systems
++           that display their link state database."
++       ::= { ospfGroups 12 }
++
++
++    ospfAreaAggregateGroup    OBJECT-GROUP
++        OBJECTS {
++                    ospfAreaAggregateAreaID,
++                    ospfAreaAggregateLsdbType,
++                    ospfAreaAggregateNet,
++                    ospfAreaAggregateMask,
++                    ospfAreaAggregateStatus,
++                    ospfAreaAggregateEffect
++        }
++        STATUS  current
++        DESCRIPTION
++           "These objects are required for OSPF systems."
++       ::= { ospfGroups 13 }
++
++END
+--- /dev/null
++++ b/mibs/OSPF-TRAP-MIB.txt
+@@ -0,0 +1,443 @@
++OSPF-TRAP-MIB DEFINITIONS ::= BEGIN
++
++    IMPORTS
++            MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, IpAddress
++                FROM SNMPv2-SMI
++            MODULE-COMPLIANCE, OBJECT-GROUP
++                FROM SNMPv2-CONF
++            ospfRouterId, ospfIfIpAddress, ospfAddressLessIf, ospfIfState,
++            ospfVirtIfAreaId, ospfVirtIfNeighbor, ospfVirtIfState,
++            ospfNbrIpAddr, ospfNbrAddressLessIndex, ospfNbrRtrId,
++            ospfNbrState, ospfVirtNbrArea, ospfVirtNbrRtrId, ospfVirtNbrState,
++            ospfLsdbType, ospfLsdbLsid, ospfLsdbRouterId, ospfLsdbAreaId,
++            ospfExtLsdbLimit, ospf
++                FROM OSPF-MIB;
++
++    ospfTrap MODULE-IDENTITY
++           LAST-UPDATED "9501201225Z" -- Fri Jan 20 12:25:50 PST 1995
++           ORGANIZATION "IETF OSPF Working Group"
++           CONTACT-INFO
++           "                      Fred Baker
++           Postal:                Cisco Systems
++                                  519 Lado Drive
++                                  Santa Barbara, California 93111
++           Tel:                   +1 805 681 0115
++           E-Mail:                fred@cisco.com
++
++                                  Rob Coltun
++           Postal:                RainbowBridge Communications
++           Tel:                   (301) 340-9416
++           E-Mail:                rcoltun@rainbow-bridge.com"
++       DESCRIPTION
++          "The MIB module to describe traps for  the  OSPF
++          Version 2 Protocol."
++      ::= { ospf 16 }
++
++-- Trap Support Objects
++
++--         The following are support objects for the OSPF traps.
++
++ospfTrapControl OBJECT IDENTIFIER ::= { ospfTrap 1 }
++ospfTraps OBJECT IDENTIFIER ::= { ospfTrap 2 }
++
++    ospfSetTrap OBJECT-TYPE
++        SYNTAX   OCTET STRING (SIZE(4))
++        MAX-ACCESS   read-write
++        STATUS   current
++        DESCRIPTION
++           "A four-octet string serving as a bit  map  for
++           the trap events defined by the OSPF traps. This
++           object is used to enable and  disable  specific
++           OSPF   traps   where  a  1  in  the  bit  field
++           represents enabled.  The right-most bit  (least
++           significant) represents trap 0."
++       ::= { ospfTrapControl 1 }
++
++
++    ospfConfigErrorType OBJECT-TYPE
++        SYNTAX   INTEGER   {
++                    badVersion (1),
++                    areaMismatch (2),
++                    unknownNbmaNbr (3), -- Router is Dr eligible
++                    unknownVirtualNbr (4),
++                    authTypeMismatch(5),
++                    authFailure (6),
++                    netMaskMismatch (7),
++                    helloIntervalMismatch (8),
++                    deadIntervalMismatch (9),
++                    optionMismatch (10) }
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "Potential types  of  configuration  conflicts.
++           Used  by the ospfConfigError and ospfConfigVir-
++           tError traps."
++   ::= { ospfTrapControl 2 }
++
++
++    ospfPacketType OBJECT-TYPE
++        SYNTAX   INTEGER   {
++                    hello (1),
++                    dbDescript (2),
++                    lsReq (3),
++                    lsUpdate (4),
++                    lsAck (5) }
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "OSPF packet types."
++   ::= { ospfTrapControl 3 }
++
++
++    ospfPacketSrc OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The IP address of an inbound packet that  can-
++           not be identified by a neighbor instance."
++       ::= { ospfTrapControl 4 }
++
++
++-- Traps
++
++
++    ospfIfStateChange NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfIfIpAddress,
++                    ospfAddressLessIf,
++                    ospfIfState   -- The new state
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An ospfIfStateChange trap signifies that there
++           has been a change in the state of a non-virtual
++           OSPF interface. This trap should  be  generated
++           when  the interface state regresses (e.g., goes
++           from Dr to Down) or progresses  to  a  terminal
++           state  (i.e.,  Point-to-Point, DR Other, Dr, or
++           Backup)."
++   ::= { ospfTraps 16 }
++
++
++    ospfVirtIfStateChange NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfVirtIfAreaId,
++                    ospfVirtIfNeighbor,
++                    ospfVirtIfState  -- The new state
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An ospfIfStateChange trap signifies that there
++           has  been a change in the state of an OSPF vir-
++           tual interface.
++           This trap should be generated when  the  inter-
++           face  state  regresses  (e.g., goes from Point-
++           to-Point to Down) or progresses to  a  terminal
++           state (i.e., Point-to-Point)."
++   ::= { ospfTraps 1 }
++
++
++    ospfNbrStateChange NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfNbrIpAddr,
++                    ospfNbrAddressLessIndex,
++                    ospfNbrRtrId,
++                    ospfNbrState  -- The new state
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An  ospfNbrStateChange  trap  signifies   that
++           there  has been a change in the state of a non-
++           virtual OSPF neighbor.   This  trap  should  be
++           generated  when  the  neighbor  state regresses
++           (e.g., goes from Attempt or Full  to  1-Way  or
++           Down)  or progresses to a terminal state (e.g.,
++           2-Way or Full).  When an  neighbor  transitions
++           from  or  to Full on non-broadcast multi-access
++           and broadcast networks, the trap should be gen-
++           erated  by the designated router.  A designated
++           router transitioning to Down will be  noted  by
++           ospfIfStateChange."
++   ::= { ospfTraps 2 }
++
++
++    ospfVirtNbrStateChange NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfVirtNbrArea,
++                    ospfVirtNbrRtrId,
++                    ospfVirtNbrState  -- The new state
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An ospfIfStateChange trap signifies that there
++           has  been a change in the state of an OSPF vir-
++           tual neighbor.  This trap should  be  generated
++           when  the  neighbor state regresses (e.g., goes
++           from Attempt or  Full  to  1-Way  or  Down)  or
++           progresses to a terminal state (e.g., Full)."
++   ::= { ospfTraps 3 }
++    ospfIfConfigError NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfIfIpAddress,
++                    ospfAddressLessIf,
++                    ospfPacketSrc,  -- The source IP address
++                    ospfConfigErrorType, -- Type of error
++                    ospfPacketType
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An ospfIfConfigError  trap  signifies  that  a
++           packet  has  been received on a non-virtual in-
++           terface  from  a  router  whose   configuration
++           parameters  conflict  with this router's confi-
++           guration parameters.  Note that the  event  op-
++           tionMismatch  should  cause  a  trap only if it
++           prevents an adjacency from forming."
++                  ::= { ospfTraps 4 }
++
++
++    ospfVirtIfConfigError NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfVirtIfAreaId,
++                    ospfVirtIfNeighbor,
++                    ospfConfigErrorType, -- Type of error
++                    ospfPacketType
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An ospfConfigError trap signifies that a pack-
++           et  has  been  received  on a virtual interface
++           from a router  whose  configuration  parameters
++           conflict   with   this  router's  configuration
++           parameters.  Note that the event optionMismatch
++           should  cause a trap only if it prevents an ad-
++           jacency from forming."
++   ::= { ospfTraps 5 }
++
++
++    ospfIfAuthFailure NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfIfIpAddress,
++                    ospfAddressLessIf,
++                    ospfPacketSrc,  -- The source IP address
++                    ospfConfigErrorType, -- authTypeMismatch or
++                                         -- authFailure
++                    ospfPacketType
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An ospfIfAuthFailure  trap  signifies  that  a
++           packet  has  been received on a non-virtual in-
++           terface from a router whose authentication  key
++           or  authentication  type  conflicts  with  this
++           router's authentication key  or  authentication
++           type."
++   ::= { ospfTraps 6 }
++
++
++    ospfVirtIfAuthFailure NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfVirtIfAreaId,
++                    ospfVirtIfNeighbor,
++                    ospfConfigErrorType, -- authTypeMismatch or
++                                         -- authFailure
++                    ospfPacketType
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An ospfVirtIfAuthFailure trap signifies that a
++           packet has been received on a virtual interface
++           from a router whose authentication key  or  au-
++           thentication  type conflicts with this router's
++           authentication key or authentication type."
++   ::= { ospfTraps 7 }
++
++
++    ospfIfRxBadPacket NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfIfIpAddress,
++                    ospfAddressLessIf,
++                    ospfPacketSrc,  -- The source IP address
++                    ospfPacketType
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An ospfIfRxBadPacket trap  signifies  that  an
++           OSPF  packet has been received on a non-virtual
++           interface that cannot be parsed."
++   ::= { ospfTraps 8 }
++
++    ospfVirtIfRxBadPacket NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfVirtIfAreaId,
++                    ospfVirtIfNeighbor,
++                    ospfPacketType
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An ospfRxBadPacket trap signifies that an OSPF
++           packet has been received on a virtual interface
++           that cannot be parsed."
++   ::= { ospfTraps 9 }
++
++
++    ospfTxRetransmit NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfIfIpAddress,
++                    ospfAddressLessIf,
++                    ospfNbrRtrId, -- Destination
++                    ospfPacketType,
++                    ospfLsdbType,
++                    ospfLsdbLsid,
++                    ospfLsdbRouterId
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An ospfTxRetransmit  trap  signifies  than  an
++           OSPF  packet  has  been retransmitted on a non-
++           virtual interface.  All packets that may be re-
++           transmitted  are associated with an LSDB entry.
++           The LS type, LS ID, and Router ID are  used  to
++           identify the LSDB entry."
++   ::= { ospfTraps 10 }
++
++
++    ospfVirtIfTxRetransmit NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfVirtIfAreaId,
++                    ospfVirtIfNeighbor,
++                    ospfPacketType,
++                    ospfLsdbType,
++                    ospfLsdbLsid,
++                    ospfLsdbRouterId
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An ospfTxRetransmit  trap  signifies  than  an
++           OSPF packet has been retransmitted on a virtual
++           interface.  All packets that may be retransmit-
++           ted  are  associated with an LSDB entry. The LS
++           type, LS ID, and Router ID are used to identify
++           the LSDB entry."
++   ::= { ospfTraps 11 }
++
++
++    ospfOriginateLsa NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfLsdbAreaId,  -- 0.0.0.0 for AS Externals
++                    ospfLsdbType,
++                    ospfLsdbLsid,
++                    ospfLsdbRouterId
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An ospfOriginateLsa trap signifies that a  new
++           LSA  has  been originated by this router.  This
++           trap should not be invoked for simple refreshes
++           of  LSAs  (which happesn every 30 minutes), but
++           instead will only be invoked  when  an  LSA  is
++           (re)originated due to a topology change.  Addi-
++           tionally, this trap does not include LSAs  that
++           are  being  flushed  because  they have reached
++           MaxAge."
++   ::= { ospfTraps 12 }
++
++
++    ospfMaxAgeLsa NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfLsdbAreaId,  -- 0.0.0.0 for AS Externals
++                    ospfLsdbType,
++                    ospfLsdbLsid,
++                    ospfLsdbRouterId
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An ospfMaxAgeLsa trap signifies  that  one  of
++           the LSA in the router's link-state database has
++           aged to MaxAge."
++   ::= { ospfTraps 13 }
++
++
++    ospfLsdbOverflow NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfExtLsdbLimit
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An ospfLsdbOverflow trap  signifies  that  the
++           number of LSAs in the router's link-state data-
++           base has exceeded ospfExtLsdbLimit."
++   ::= { ospfTraps 14 }
++
++
++    ospfLsdbApproachingOverflow NOTIFICATION-TYPE
++        OBJECTS {
++                    ospfRouterId, -- The originator of the trap
++                    ospfExtLsdbLimit
++                  }
++        STATUS             current
++        DESCRIPTION
++           "An ospfLsdbApproachingOverflow trap  signifies
++           that  the  number of LSAs in the router's link-
++           state database has exceeded ninety  percent  of
++           ospfExtLsdbLimit."
++   ::= { ospfTraps 15 }
++
++
++-- conformance information
++
++ospfTrapConformance OBJECT IDENTIFIER ::= { ospfTrap 3 }
++
++ospfTrapGroups      OBJECT IDENTIFIER ::= { ospfTrapConformance 1 }
++ospfTrapCompliances OBJECT IDENTIFIER ::= { ospfTrapConformance 2 }
++
++-- compliance statements
++
++    ospfTrapCompliance MODULE-COMPLIANCE
++        STATUS  current
++        DESCRIPTION
++           "The compliance statement "
++       MODULE  -- this module
++       MANDATORY-GROUPS { ospfTrapControlGroup }
++
++
++        GROUP       ospfTrapControlGroup
++        DESCRIPTION
++           "This group is optional but recommended for all
++           OSPF systems"
++       ::= { ospfTrapCompliances 1 }
++
++
++-- units of conformance
++
++    ospfTrapControlGroup    OBJECT-GROUP
++        OBJECTS {
++                           ospfSetTrap,
++                           ospfConfigErrorType,
++                           ospfPacketType,
++                           ospfPacketSrc
++        }
++        STATUS  current
++        DESCRIPTION
++           "These objects are required  to  control  traps
++           from OSPF systems."
++       ::= { ospfTrapGroups 1 }
++
++
++END
+--- /dev/null
++++ b/mibs/RIPv2-MIB.txt
+@@ -0,0 +1,530 @@
++   RIPv2-MIB DEFINITIONS ::= BEGIN
++
++   IMPORTS
++       MODULE-IDENTITY, OBJECT-TYPE, Counter32,
++       TimeTicks, IpAddress                     FROM SNMPv2-SMI
++       TEXTUAL-CONVENTION, RowStatus            FROM SNMPv2-TC
++       MODULE-COMPLIANCE, OBJECT-GROUP          FROM SNMPv2-CONF
++       mib-2                                    FROM RFC1213-MIB;
++
++   --  This MIB module uses the extended OBJECT-TYPE macro as
++   --  defined in [9].
++
++   rip2  MODULE-IDENTITY
++           LAST-UPDATED "9407272253Z"      -- Wed Jul 27 22:53:04 PDT 1994
++           ORGANIZATION "IETF RIP-II Working Group"
++           CONTACT-INFO
++          "       Fred Baker
++          Postal: Cisco Systems
++                  519 Lado Drive
++                  Santa Barbara, California 93111
++          Tel:    +1 805 681 0115
++          E-Mail: fbaker@cisco.com
++
++          Postal: Gary Malkin
++                  Xylogics, Inc.
++                  53 Third Avenue
++                  Burlington, MA  01803
++
++          Phone:  (617) 272-8140
++          EMail:  gmalkin@Xylogics.COM"
++      DESCRIPTION
++         "The MIB module to describe the RIP2 Version 2 Protocol"
++     ::= { mib-2 23 }
++
++ --  RIP-2 Management Information Base
++
++ -- the RouteTag type represents the contents of the
++ -- Route Domain field in the packet header or route entry.
++ -- The use of the Route Domain is deprecated.
++
++ RouteTag ::= TEXTUAL-CONVENTION
++     STATUS      current
++     DESCRIPTION
++        "the RouteTag type represents the contents of the Route Domain
++        field in the packet header or route entry"
++    SYNTAX      OCTET STRING (SIZE (2))
++
++--4.1 Global Counters
++
++--      The RIP-2 Globals Group.
++--      Implementation of this group is mandatory for systems
++--      which implement RIP-2.
++
++-- These counters are intended to facilitate debugging quickly
++-- changing routes or failing neighbors
++
++rip2Globals OBJECT IDENTIFIER ::= { rip2 1 }
++
++    rip2GlobalRouteChanges OBJECT-TYPE
++        SYNTAX   Counter32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The number of route changes made to the IP Route
++           Database by RIP.  This does not include the refresh
++           of a route's age."
++       ::= { rip2Globals 1 }
++
++    rip2GlobalQueries OBJECT-TYPE
++        SYNTAX   Counter32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The number of responses sent to RIP queries
++           from other systems."
++       ::= { rip2Globals 2 }
++
++--4.2 RIP Interface Tables
++
++--  RIP Interfaces Groups
++--  Implementation of these Groups is mandatory for systems
++--  which implement RIP-2.
++
++-- The RIP Interface Status Table.
++
++    rip2IfStatTable OBJECT-TYPE
++        SYNTAX   SEQUENCE OF Rip2IfStatEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "A list of subnets which require separate
++           status monitoring in RIP."
++       ::= { rip2 2 }
++
++   rip2IfStatEntry OBJECT-TYPE
++       SYNTAX   Rip2IfStatEntry
++       MAX-ACCESS   not-accessible
++       STATUS   current
++       DESCRIPTION
++          "A Single Routing Domain in a single Subnet."
++      INDEX { rip2IfStatAddress }
++      ::= { rip2IfStatTable 1 }
++
++    Rip2IfStatEntry ::=
++        SEQUENCE {
++            rip2IfStatAddress
++                IpAddress,
++            rip2IfStatRcvBadPackets
++                Counter32,
++            rip2IfStatRcvBadRoutes
++                Counter32,
++            rip2IfStatSentUpdates
++                Counter32,
++            rip2IfStatStatus
++                RowStatus
++    }
++
++    rip2IfStatAddress OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The IP Address of this system on the indicated
++           subnet. For unnumbered interfaces, the value 0.0.0.N,
++           where the least significant 24 bits (N) is the ifIndex
++           for the IP Interface in network byte order."
++       ::= { rip2IfStatEntry 1 }
++
++    rip2IfStatRcvBadPackets OBJECT-TYPE
++        SYNTAX   Counter32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The number of RIP response packets received by
++           the RIP process which were subsequently discarded
++           for any reason (e.g. a version 0 packet, or an
++           unknown command type)."
++       ::= { rip2IfStatEntry 2 }
++
++    rip2IfStatRcvBadRoutes OBJECT-TYPE
++        SYNTAX   Counter32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The number of routes, in valid RIP packets,
++           which were ignored for any reason (e.g. unknown
++           address family, or invalid metric)."
++       ::= { rip2IfStatEntry 3 }
++
++    rip2IfStatSentUpdates OBJECT-TYPE
++        SYNTAX   Counter32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The number of triggered RIP updates actually
++           sent on this interface.  This explicitly does
++           NOT include full updates sent containing new
++           information."
++       ::= { rip2IfStatEntry 4 }
++
++    rip2IfStatStatus OBJECT-TYPE
++        SYNTAX   RowStatus
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "Writing invalid has the effect of deleting
++           this interface."
++       ::= { rip2IfStatEntry 5 }
++
++-- The RIP Interface Configuration Table.
++
++    rip2IfConfTable OBJECT-TYPE
++        SYNTAX   SEQUENCE OF Rip2IfConfEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "A list of subnets which require separate
++           configuration in RIP."
++       ::= { rip2 3 }
++
++   rip2IfConfEntry OBJECT-TYPE
++       SYNTAX   Rip2IfConfEntry
++       MAX-ACCESS   not-accessible
++       STATUS   current
++       DESCRIPTION
++          "A Single Routing Domain in a single Subnet."
++      INDEX { rip2IfConfAddress }
++      ::= { rip2IfConfTable 1 }
++
++    Rip2IfConfEntry ::=
++        SEQUENCE {
++            rip2IfConfAddress
++                IpAddress,
++            rip2IfConfDomain
++                RouteTag,
++            rip2IfConfAuthType
++                INTEGER,
++            rip2IfConfAuthKey
++                OCTET STRING (SIZE(0..16)),
++            rip2IfConfSend
++                INTEGER,
++            rip2IfConfReceive
++                INTEGER,
++            rip2IfConfDefaultMetric
++                INTEGER,
++            rip2IfConfStatus
++                RowStatus,
++            rip2IfConfSrcAddress
++                IpAddress
++    }
++
++    rip2IfConfAddress OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The IP Address of this system on the indicated
++           subnet.  For unnumbered interfaces, the value 0.0.0.N,
++           where the least significant 24 bits (N) is the ifIndex
++           for the IP Interface in network byte order."
++       ::= { rip2IfConfEntry 1 }
++
++    rip2IfConfDomain OBJECT-TYPE
++        SYNTAX   RouteTag
++        MAX-ACCESS   read-create
++        STATUS   obsolete
++        DESCRIPTION
++           "Value inserted into the Routing Domain field
++           of all RIP packets sent on this interface."
++       DEFVAL { '0000'h }
++       ::= { rip2IfConfEntry 2 }
++
++    rip2IfConfAuthType OBJECT-TYPE
++        SYNTAX   INTEGER {
++                    noAuthentication (1),
++                    simplePassword (2),
++                    md5 (3)
++                 }
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The type of Authentication used on this
++           interface."
++       DEFVAL { noAuthentication }
++       ::= { rip2IfConfEntry 3 }
++
++    rip2IfConfAuthKey OBJECT-TYPE
++        SYNTAX   OCTET STRING (SIZE(0..16))
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The value to be used as the Authentication Key
++           whenever the corresponding instance of
++           rip2IfConfAuthType has a value other than
++           noAuthentication.  A modification of the corresponding
++           instance of rip2IfConfAuthType does not modify
++           the rip2IfConfAuthKey value.  If a string shorter
++           than 16 octets is supplied, it will be left-
++           justified and padded to 16 octets, on the right,
++           with nulls (0x00).
++
++           Reading this object always results in an  OCTET
++           STRING of length zero; authentication may not
++           be bypassed by reading the MIB object."
++       DEFVAL { ''h }
++       ::= { rip2IfConfEntry 4 }
++
++    rip2IfConfSend OBJECT-TYPE
++        SYNTAX   INTEGER {
++                    doNotSend (1),
++                    ripVersion1 (2),
++                    rip1Compatible (3),
++                    ripVersion2 (4),
++                    ripV1Demand (5),
++                    ripV2Demand (6)
++                 }
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "What the router sends on this interface.
++           ripVersion1 implies sending RIP updates compliant
++           with  RFC  1058.   rip1Compatible implies
++           broadcasting RIP-2 updates using RFC 1058 route
++           subsumption rules.  ripVersion2 implies
++           multicasting RIP-2 updates.  ripV1Demand indicates
++           the use of Demand RIP on a WAN interface under RIP
++           Version 1 rules.  ripV2Demand indicates the use of
++           Demand RIP on a WAN interface under Version 2 rules."
++       DEFVAL { rip1Compatible }
++       ::= { rip2IfConfEntry 5 }
++
++    rip2IfConfReceive OBJECT-TYPE
++        SYNTAX   INTEGER {
++                    rip1 (1),
++                    rip2 (2),
++                    rip1OrRip2 (3),
++                    doNotRecieve (4)
++                 }
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "This indicates which version of RIP updates
++           are to be accepted.  Note that rip2 and
++           rip1OrRip2 implies reception of multicast
++           packets."
++       DEFVAL { rip1OrRip2 }
++       ::= { rip2IfConfEntry 6 }
++
++    rip2IfConfDefaultMetric OBJECT-TYPE
++        SYNTAX   INTEGER ( 0..15 )
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "This variable indicates the metric that is to
++           be used for the default route entry in RIP updates
++           originated on this interface.  A value of zero
++           indicates that no default route should be
++           originated; in this case, a default route via
++           another router may be propagated."
++       ::= { rip2IfConfEntry 7 }
++
++    rip2IfConfStatus OBJECT-TYPE
++        SYNTAX   RowStatus
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "Writing invalid has  the  effect  of  deleting
++           this interface."
++       ::= { rip2IfConfEntry 8 }
++
++    rip2IfConfSrcAddress OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-create
++        STATUS   current
++        DESCRIPTION
++           "The IP Address this system will use as a source
++            address on this interface.  If it is a numbered
++            interface, this MUST be the same value as
++            rip2IfConfAddress.  On unnumbered interfaces,
++            it must be the value of rip2IfConfAddress for
++            some interface on the system."
++       ::= { rip2IfConfEntry 9 }
++
++--4.3 Peer Table
++
++--  Peer Table
++
++--      The RIP Peer Group
++--      Implementation of this Group is Optional
++
++--      This group provides information about active peer
++--      relationships intended to assist in debugging.  An
++--      active peer is a router from which a valid RIP
++--      updated has been heard in the last 180 seconds.
++
++    rip2PeerTable OBJECT-TYPE
++        SYNTAX   SEQUENCE OF Rip2PeerEntry
++        MAX-ACCESS   not-accessible
++        STATUS   current
++        DESCRIPTION
++           "A list of RIP Peers."
++       ::= { rip2 4 }
++
++   rip2PeerEntry OBJECT-TYPE
++       SYNTAX   Rip2PeerEntry
++       MAX-ACCESS   not-accessible
++       STATUS   current
++       DESCRIPTION
++          "Information regarding a single routing peer."
++      INDEX { rip2PeerAddress, rip2PeerDomain }
++      ::= { rip2PeerTable 1 }
++
++    Rip2PeerEntry ::=
++        SEQUENCE {
++            rip2PeerAddress
++                IpAddress,
++            rip2PeerDomain
++                RouteTag,
++            rip2PeerLastUpdate
++                TimeTicks,
++            rip2PeerVersion
++                INTEGER,
++            rip2PeerRcvBadPackets
++                Counter32,
++            rip2PeerRcvBadRoutes
++                Counter32
++            }
++
++    rip2PeerAddress OBJECT-TYPE
++        SYNTAX   IpAddress
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The IP Address that the peer is using as its source
++            address.  Note that on an unnumbered link, this may
++            not be a member of any subnet on the system."
++       ::= { rip2PeerEntry 1 }
++
++    rip2PeerDomain OBJECT-TYPE
++        SYNTAX   RouteTag
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The value in the Routing Domain field  in  RIP
++           packets received from the peer.  As domain suuport
++           is deprecated, this must be zero."
++       ::= { rip2PeerEntry 2 }
++
++    rip2PeerLastUpdate OBJECT-TYPE
++        SYNTAX   TimeTicks
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The value of sysUpTime when the most recent
++           RIP update was received from this system."
++       ::= { rip2PeerEntry 3 }
++
++    rip2PeerVersion OBJECT-TYPE
++        SYNTAX   INTEGER ( 0..255 )
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The RIP version number in the header of the
++           last RIP packet received."
++       ::= { rip2PeerEntry 4 }
++
++    rip2PeerRcvBadPackets OBJECT-TYPE
++        SYNTAX   Counter32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The number of RIP response packets from this
++           peer discarded as invalid."
++       ::= { rip2PeerEntry 5 }
++
++
++    rip2PeerRcvBadRoutes OBJECT-TYPE
++        SYNTAX   Counter32
++        MAX-ACCESS   read-only
++        STATUS   current
++        DESCRIPTION
++           "The number of routes from this peer that were
++           ignored because the entry format was invalid."
++       ::= { rip2PeerEntry 6 }
++
++-- conformance information
++
++rip2Conformance OBJECT IDENTIFIER ::= { rip2 5 }
++
++rip2Groups      OBJECT IDENTIFIER ::= { rip2Conformance 1 }
++rip2Compliances OBJECT IDENTIFIER ::= { rip2Conformance 2 }
++
++-- compliance statements
++rip2Compliance MODULE-COMPLIANCE
++    STATUS  current
++    DESCRIPTION
++       "The compliance statement "
++    MODULE  -- this module
++    MANDATORY-GROUPS {
++                 rip2GlobalGroup,
++                 rip2IfStatGroup,
++                 rip2IfConfGroup,
++                 rip2PeerGroup
++        }
++    GROUP       rip2GlobalGroup
++    DESCRIPTION
++       "This group defines global controls for RIP-II systems."
++    GROUP       rip2IfStatGroup
++    DESCRIPTION
++       "This group defines interface statistics for RIP-II systems."
++    GROUP       rip2IfConfGroup
++    DESCRIPTION
++       "This group defines interface configuration for RIP-II systems."
++    GROUP       rip2PeerGroup
++    DESCRIPTION
++       "This group defines peer information for RIP-II systems."
++    ::= { rip2Compliances 1 }
++
++-- units of conformance
++
++rip2GlobalGroup    OBJECT-GROUP
++    OBJECTS {
++                rip2GlobalRouteChanges,
++                rip2GlobalQueries
++    }
++    STATUS  current
++    DESCRIPTION
++       "This group defines global controls for RIP-II systems."
++    ::= { rip2Groups 1 }
++rip2IfStatGroup    OBJECT-GROUP
++    OBJECTS {
++            rip2IfStatAddress,
++            rip2IfStatRcvBadPackets,
++            rip2IfStatRcvBadRoutes,
++            rip2IfStatSentUpdates,
++            rip2IfStatStatus
++    }
++    STATUS  current
++    DESCRIPTION
++       "This group defines interface statistics for RIP-II systems."
++    ::= { rip2Groups 2 }
++rip2IfConfGroup    OBJECT-GROUP
++    OBJECTS {
++            rip2IfConfAddress,
++            rip2IfConfAuthType,
++            rip2IfConfAuthKey,
++            rip2IfConfSend,
++            rip2IfConfReceive,
++            rip2IfConfDefaultMetric,
++            rip2IfConfStatus,
++            rip2IfConfSrcAddress
++    }
++    STATUS  current
++    DESCRIPTION
++       "This group defines interface configuration for RIP-II systems."
++    ::= { rip2Groups 3 }
++rip2PeerGroup    OBJECT-GROUP
++    OBJECTS {
++            rip2PeerAddress,
++            rip2PeerDomain,
++            rip2PeerLastUpdate,
++            rip2PeerVersion,
++            rip2PeerRcvBadPackets,
++            rip2PeerRcvBadRoutes
++    }
++    STATUS  current
++    DESCRIPTION
++       "This group defines peer information for RIP-II systems."
++    ::= { rip2Groups 4 }
++END
+--- /dev/null
++++ b/mibs/SOURCE-ROUTING-MIB.txt
+@@ -0,0 +1,452 @@
++SOURCE-ROUTING-MIB DEFINITIONS ::= BEGIN
++
++IMPORTS
++        Counter, Gauge
++                FROM RFC1155-SMI
++        dot1dBridge, dot1dSr
++                FROM BRIDGE-MIB
++        OBJECT-TYPE
++                FROM RFC-1212;
++
++-- groups in the SR MIB
++
++-- dot1dSr is imported from the Bridge MIB
++
++dot1dPortPair   OBJECT IDENTIFIER ::= { dot1dBridge 10 }
++
++-- the dot1dSr group
++
++-- this group is implemented by those bridges that
++-- support the source route bridging mode, including Source
++-- Routing and SRT bridges.
++
++dot1dSrPortTable OBJECT-TYPE
++    SYNTAX  SEQUENCE OF Dot1dSrPortEntry
++    ACCESS  not-accessible
++    STATUS  mandatory
++    DESCRIPTION
++            "A table that contains information about every
++            port that is associated with this source route
++            bridge."
++    ::= { dot1dSr 1 }
++
++dot1dSrPortEntry OBJECT-TYPE
++    SYNTAX  Dot1dSrPortEntry
++    ACCESS  not-accessible
++    STATUS  mandatory
++    DESCRIPTION
++            "A list of information for each port of a source
++            route bridge."
++    INDEX   { dot1dSrPort }
++
++    ::= { dot1dSrPortTable 1 }
++
++Dot1dSrPortEntry ::=
++    SEQUENCE {
++        dot1dSrPort
++            INTEGER,
++        dot1dSrPortHopCount
++            INTEGER,
++        dot1dSrPortLocalSegment
++            INTEGER,
++        dot1dSrPortBridgeNum
++            INTEGER,
++        dot1dSrPortTargetSegment
++            INTEGER,
++        dot1dSrPortLargestFrame
++            INTEGER,
++        dot1dSrPortSTESpanMode
++            INTEGER,
++        dot1dSrPortSpecInFrames
++            Counter,
++        dot1dSrPortSpecOutFrames
++            Counter,
++        dot1dSrPortApeInFrames
++            Counter,
++        dot1dSrPortApeOutFrames
++            Counter,
++        dot1dSrPortSteInFrames
++            Counter,
++        dot1dSrPortSteOutFrames
++            Counter,
++        dot1dSrPortSegmentMismatchDiscards
++            Counter,
++        dot1dSrPortDuplicateSegmentDiscards
++            Counter,
++        dot1dSrPortHopCountExceededDiscards
++            Counter,
++        dot1dSrPortDupLanIdOrTreeErrors
++            Counter,
++        dot1dSrPortLanIdMismatches
++            Counter
++    }
++
++dot1dSrPort OBJECT-TYPE
++    SYNTAX  INTEGER (1..65535)
++    ACCESS  read-only
++    STATUS  mandatory
++    DESCRIPTION
++            "The port number of the port for which this entry
++
++            contains Source Route management information."
++    ::= { dot1dSrPortEntry 1 }
++
++dot1dSrPortHopCount OBJECT-TYPE
++    SYNTAX  INTEGER
++    ACCESS  read-write
++    STATUS  mandatory
++    DESCRIPTION
++            "The maximum number of routing descriptors allowed
++            in an All Paths or Spanning Tree Explorer frames."
++    ::= { dot1dSrPortEntry 2 }
++
++dot1dSrPortLocalSegment OBJECT-TYPE
++    SYNTAX  INTEGER
++    ACCESS  read-write
++    STATUS  mandatory
++    DESCRIPTION
++            "The segment number that uniquely identifies the
++            segment to which this port is connected. Current
++            source routing protocols limit this value to the
++            range: 0 through 4095. (The value 0 is used by
++            some management applications for special test
++            cases.) A value of 65535 signifies that no segment
++            number is assigned to this port."
++    ::= { dot1dSrPortEntry 3 }
++
++dot1dSrPortBridgeNum OBJECT-TYPE
++    SYNTAX  INTEGER
++    ACCESS  read-write
++    STATUS  mandatory
++    DESCRIPTION
++            "A bridge number uniquely identifies a bridge when
++            more than one bridge is used to span the same two
++            segments.  Current source routing protocols limit
++            this value to the range: 0 through 15. A value of
++            65535 signifies that no bridge number is assigned
++            to this bridge."
++    ::= { dot1dSrPortEntry 4 }
++
++dot1dSrPortTargetSegment OBJECT-TYPE
++    SYNTAX  INTEGER
++    ACCESS  read-write
++    STATUS  mandatory
++    DESCRIPTION
++            "The segment number that corresponds to the target
++            segment this port is considered to be connected to
++            by the bridge.  Current source routing protocols
++            limit this value to the range: 0 through 4095.
++
++            (The value 0 is used by some management
++            applications for special test cases.) A value of
++            65535 signifies that no target segment is assigned
++            to this port."
++    ::= { dot1dSrPortEntry 5 }
++
++-- It would be nice if we could use ifMtu as the size of the
++-- largest frame, but we can't because ifMtu is defined to be
++-- the size that the (inter-)network layer can use which can
++-- differ from the MAC layer (especially if several layers of
++-- encapsulation are used).
++
++dot1dSrPortLargestFrame OBJECT-TYPE
++    SYNTAX  INTEGER
++    ACCESS  read-write
++    STATUS  mandatory
++    DESCRIPTION
++            "The maximum size of the INFO field (LLC and
++            above) that this port can send/receive.  It does
++            not include any MAC level (framing) octets.  The
++            value of this object is used by this bridge to
++            determine whether a modification of the
++            LargestFrame (LF, see [14]) field of the Routing
++            Control field of the Routing Information Field is
++            necessary.
++
++            64 valid values are defined by the IEEE 802.5M SRT
++            Addendum: 516, 635, 754, 873, 993, 1112, 1231,
++            1350, 1470, 1542, 1615, 1688, 1761, 1833, 1906,
++            1979, 2052, 2345, 2638, 2932, 3225, 3518, 3812,
++            4105, 4399, 4865, 5331, 5798, 6264, 6730, 7197,
++            7663, 8130, 8539, 8949, 9358, 9768, 10178, 10587,
++            10997, 11407, 12199, 12992, 13785, 14578, 15370,
++            16163, 16956, 17749, 20730, 23711, 26693, 29674,
++            32655, 35637, 38618, 41600, 44591, 47583, 50575,
++            53567, 56559, 59551, and 65535.
++
++            An illegal value will not be accepted by the
++            bridge."
++    ::= { dot1dSrPortEntry 6 }
++
++dot1dSrPortSTESpanMode OBJECT-TYPE
++    SYNTAX  INTEGER {
++                auto-span(1),
++                disabled(2),
++                forced(3)
++            }
++    ACCESS  read-write
++    STATUS  mandatory
++    DESCRIPTION
++            "Determines how this port behaves when presented
++            with a Spanning Tree Explorer frame.  The value
++            'disabled(2)' indicates that the port will not
++            accept or send Spanning Tree Explorer packets; any
++            STE packets received will be silently discarded.
++            The value 'forced(3)' indicates the port will
++            always accept and propagate Spanning Tree Explorer
++            frames.  This allows a manually configured
++            Spanning Tree for this class of packet to be
++            configured.  Note that unlike transparent
++            bridging, this is not catastrophic to the network
++            if there are loops.  The value 'auto-span(1)' can
++            only be returned by a bridge that both implements
++            the Spanning Tree Protocol and has use of the
++            protocol enabled on this port. The behavior of the
++            port for Spanning Tree Explorer frames is
++            determined by the state of dot1dStpPortState.  If
++            the port is in the 'forwarding' state, the frame
++            will be accepted or propagated.  Otherwise, it
++            will be silently discarded."
++    ::= { dot1dSrPortEntry 7 }
++
++dot1dSrPortSpecInFrames OBJECT-TYPE
++    SYNTAX  Counter
++    ACCESS  read-only
++    STATUS  mandatory
++    DESCRIPTION
++            "The number of Specifically Routed frames, also
++            referred to as Source Routed Frames, that have
++            been received from this port's segment."
++    ::= { dot1dSrPortEntry 8 }
++
++dot1dSrPortSpecOutFrames OBJECT-TYPE
++    SYNTAX  Counter
++    ACCESS  read-only
++    STATUS  mandatory
++    DESCRIPTION
++            "The number of Specifically Routed frames, also
++            referred to as Source Routed Frames, that this
++            port has transmitted on its segment."
++    ::= { dot1dSrPortEntry 9 }
++
++dot1dSrPortApeInFrames OBJECT-TYPE
++    SYNTAX  Counter
++    ACCESS  read-only
++    STATUS  mandatory
++    DESCRIPTION
++            "The number of All Paths Explorer frames, also
++            referred to as All Routes Explorer frames, that
++            have been received by this port from its segment."
++    ::= { dot1dSrPortEntry 10 }
++
++dot1dSrPortApeOutFrames OBJECT-TYPE
++    SYNTAX  Counter
++    ACCESS  read-only
++    STATUS  mandatory
++    DESCRIPTION
++            "The number of all Paths Explorer Frames, also
++            referred to as All Routes Explorer frames, that
++            have been transmitted by this port on its
++            segment."
++    ::= { dot1dSrPortEntry 11 }
++
++dot1dSrPortSteInFrames OBJECT-TYPE
++    SYNTAX  Counter
++    ACCESS  read-only
++    STATUS  mandatory
++    DESCRIPTION
++            "The number of spanning tree explorer frames that
++            have been received by this port from its segment."
++    ::= { dot1dSrPortEntry 12 }
++
++dot1dSrPortSteOutFrames OBJECT-TYPE
++    SYNTAX  Counter
++    ACCESS  read-only
++    STATUS  mandatory
++    DESCRIPTION
++            "The number of spanning tree explorer frames that
++            have been transmitted by this port on its
++            segment."
++    ::= { dot1dSrPortEntry 13 }
++
++dot1dSrPortSegmentMismatchDiscards OBJECT-TYPE
++    SYNTAX  Counter
++    ACCESS  read-only
++    STATUS  mandatory
++    DESCRIPTION
++            "The number of explorer frames that have been
++            discarded by this port because the routing
++            descriptor field contained an invalid adjacent
++            segment value."
++    ::= { dot1dSrPortEntry 14 }
++
++dot1dSrPortDuplicateSegmentDiscards OBJECT-TYPE
++    SYNTAX  Counter
++    ACCESS  read-only
++    STATUS  mandatory
++    DESCRIPTION
++            "The number of frames that have been discarded by
++            this port because the routing descriptor field
++            contained a duplicate segment identifier."
++    ::= { dot1dSrPortEntry 15 }
++
++dot1dSrPortHopCountExceededDiscards OBJECT-TYPE
++    SYNTAX  Counter
++    ACCESS  read-only
++    STATUS  mandatory
++    DESCRIPTION
++            "The number of explorer frames that have been
++            discarded by this port because the Routing
++            Information Field has exceeded the maximum route
++            descriptor length."
++    ::= { dot1dSrPortEntry 16 }
++
++dot1dSrPortDupLanIdOrTreeErrors OBJECT-TYPE
++    SYNTAX  Counter
++    ACCESS  read-only
++    STATUS  mandatory
++    DESCRIPTION
++            "The number of duplicate LAN IDs or Tree errors.
++            This helps in detection of problems in networks
++            containing older IBM Source Routing Bridges."
++    ::= { dot1dSrPortEntry 17 }
++
++dot1dSrPortLanIdMismatches OBJECT-TYPE
++    SYNTAX  Counter
++    ACCESS  read-only
++    STATUS  mandatory
++    DESCRIPTION
++            "The number of ARE and STE frames that were
++            discarded because the last LAN ID in the routing
++            information field did not equal the LAN-in ID.
++            This error can occur in implementations which do
++            only a LAN-in ID and Bridge Number check instead
++            of a LAN-in ID, Bridge Number, and LAN-out ID
++            check before they forward broadcast frames."
++    ::= { dot1dSrPortEntry 18 }
++
++-- scalar object in dot1dSr
++
++dot1dSrBridgeLfMode OBJECT-TYPE
++    SYNTAX  INTEGER {
++                mode3(1),
++                mode6(2)
++            }
++    ACCESS  read-write
++    STATUS  mandatory
++    DESCRIPTION
++            "Indicates whether the bridge operates using older
++            3 bit length negotiation fields or the newer 6 bit
++            length field in its RIF."
++    ::= { dot1dSr 2 }
++
++-- The Port-Pair Database
++
++-- Implementation of this group is optional.
++
++-- This group is implemented by those bridges that support
++-- the direct multiport model of the source route bridging
++-- mode as defined in the IEEE 802.5 SRT Addendum to
++-- 802.1d.
++
++-- Bridges implementing this group may report 65535 for
++-- dot1dSrPortBridgeNumber and dot1dSrPortTargetSegment,
++-- indicating that those objects are not applicable.
++
++dot1dPortPairTableSize OBJECT-TYPE
++    SYNTAX  Gauge
++    ACCESS  read-only
++    STATUS  mandatory
++    DESCRIPTION
++            "The total number of entries in the Bridge Port
++            Pair Database."
++    ::= { dot1dPortPair 1 }
++
++-- the Bridge Port-Pair table
++
++-- this table represents port pairs within a bridge forming
++-- a unique bridge path, as defined in the IEEE 802.5M SRT
++-- Addendum.
++
++dot1dPortPairTable OBJECT-TYPE
++    SYNTAX  SEQUENCE OF Dot1dPortPairEntry
++    ACCESS  not-accessible
++    STATUS  mandatory
++    DESCRIPTION
++            "A table that contains information about every
++
++            port pair database entity associated with this
++            source routing bridge."
++    ::= { dot1dPortPair 2 }
++
++dot1dPortPairEntry OBJECT-TYPE
++    SYNTAX  Dot1dPortPairEntry
++    ACCESS  not-accessible
++    STATUS  mandatory
++    DESCRIPTION
++            "A list of information for each port pair entity
++            of a bridge."
++    INDEX   { dot1dPortPairLowPort, dot1dPortPairHighPort }
++    ::= { dot1dPortPairTable 1 }
++
++Dot1dPortPairEntry ::=
++    SEQUENCE {
++        dot1dPortPairLowPort
++            INTEGER,
++        dot1dPortPairHighPort
++            INTEGER,
++        dot1dPortPairBridgeNum
++            INTEGER,
++        dot1dPortPairBridgeState
++            INTEGER
++    }
++
++dot1dPortPairLowPort OBJECT-TYPE
++    SYNTAX  INTEGER (1..65535)
++    ACCESS  read-write
++    STATUS  mandatory
++    DESCRIPTION
++            "The port number of the lower numbered port for
++            which this entry contains port pair database
++            information."
++    ::= { dot1dPortPairEntry 1 }
++
++dot1dPortPairHighPort OBJECT-TYPE
++    SYNTAX  INTEGER (1..65535)
++    ACCESS  read-write
++    STATUS  mandatory
++    DESCRIPTION
++            "The port number of the higher numbered port for
++            which this entry contains port pair database
++            information."
++    ::= { dot1dPortPairEntry 2 }
++
++dot1dPortPairBridgeNum OBJECT-TYPE
++    SYNTAX  INTEGER
++
++    ACCESS  read-write
++    STATUS  mandatory
++    DESCRIPTION
++            "A bridge number that uniquely identifies the path
++            provided by this source routing bridge between the
++            segments connected to dot1dPortPairLowPort and
++            dot1dPortPairHighPort.  The purpose of bridge
++            number is to disambiguate between multiple paths
++            connecting the same two LANs."
++    ::= { dot1dPortPairEntry 3 }
++
++dot1dPortPairBridgeState OBJECT-TYPE
++    SYNTAX  INTEGER {
++                enabled(1),
++                disabled(2),
++                invalid(3)
++            }
++    ACCESS  read-write
++    STATUS  mandatory
++    DESCRIPTION
++            "The state of dot1dPortPairBridgeNum.  Writing
++            'invalid(3)' to this object removes the
++            corresponding entry."
++    ::= { dot1dPortPairEntry 4 }
++
++END
diff --git a/package/network/utils/net-snmp/patches/160-no_ldconfig.patch b/package/network/utils/net-snmp/patches/160-no_ldconfig.patch
new file mode 100644
index 0000000..d9de73e
--- /dev/null
+++ b/package/network/utils/net-snmp/patches/160-no_ldconfig.patch
@@ -0,0 +1,11 @@
+--- a/configure
++++ b/configure
+@@ -15097,7 +15097,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu)
+   need_version=no
+   library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+   soname_spec='${libname}${release}${shared_ext}$major'
+-  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++  finish_cmds=''
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=no
+ 
diff --git a/package/network/utils/net-snmp/patches/170-ldflags.patch b/package/network/utils/net-snmp/patches/170-ldflags.patch
new file mode 100644
index 0000000..dd1b9fe
--- /dev/null
+++ b/package/network/utils/net-snmp/patches/170-ldflags.patch
@@ -0,0 +1,11 @@
+--- a/Makefile.top
++++ b/Makefile.top
+@@ -87,7 +87,7 @@ LIBCURRENT  = 35
+ LIBAGE      = 0
+ LIBREVISION = 0
+ 
+-LIB_LD_CMD      = $(LIBTOOL) --mode=link $(LINKCC) $(CFLAGS) -rpath $(libdir) -version-info $(LIBCURRENT):$(LIBREVISION):$(LIBAGE) -o
++LIB_LD_CMD      = $(LIBTOOL) --mode=link $(LINKCC) $(CFLAGS) -rpath $(libdir) $(LDFLAGS) -version-info $(LIBCURRENT):$(LIBREVISION):$(LIBAGE) -o
+ LIB_EXTENSION   = la
+ LIB_VERSION     =
+ LIB_LDCONFIG_CMD = $(LIBTOOL) --mode=finish $(INSTALL_PREFIX)$(libdir)
diff --git a/package/network/utils/net-snmp/patches/750-ieee802dot11.patch b/package/network/utils/net-snmp/patches/750-ieee802dot11.patch
new file mode 100644
index 0000000..a3c5c0a
--- /dev/null
+++ b/package/network/utils/net-snmp/patches/750-ieee802dot11.patch
@@ -0,0 +1,6156 @@
+--- /dev/null
++++ b/agent/mibgroup/ieee802dot11.c
+@@ -0,0 +1,4915 @@
++/****************************************************************************
++*                                                                           *
++*  File Name:           ieee802dot11.c                                      *
++*  Used By:                                                                 *
++*                                                                           *
++*  Operating System:                                                        *
++*  Purpose:                                                                 *
++*                                                                           *
++*  Comments:                                                                *
++*                                                                           *
++*  Author:              Larry Simmons                                       *
++*                       lsimmons@avantcom.com                               *
++*                       www.avantcom.com                                    *
++*                                                                           *
++*  Creation Date:       09/02/03                                            *
++*                                                                           *
++*   Ver    Date   Inits Modification                                        *
++*  ----- -------- ----- ------------                                        *
++*  0.0.1 09/02/03  LRS  created                                             *
++*  0.0.2 09/24/03  LRS  wouldn't build after fresh ./configure              *
++****************************************************************************/
++/****************************************************************************
++*                               Includes                                    *
++****************************************************************************/
++#include <net-snmp/net-snmp-config.h>
++#include <net-snmp/net-snmp-includes.h>
++#include <net-snmp/agent/net-snmp-agent-includes.h>
++#include "ieee802dot11.h"
++#include "iwlib.h"
++
++/****************************************************************************
++*                                Defines                                    *
++****************************************************************************/
++#define DISPLAYWIEXT                        // display wireless ext info
++#define TABLE_SIZE   1
++//#define MINLOADFREQ 15                    // min reload frequency in seconds
++#define MINLOADFREQ 5                       // min reload frequency in seconds      // for testing
++#define PROC_NET_DEV      "/proc/net/dev"
++#define PROC_NET_WIRELESS "/proc/net/wireless"
++
++#ifndef UCHAR
++  typedef unsigned char UCHAR;
++#endif
++
++/****************************************************************************
++*                            Private Functions                              *
++****************************************************************************/
++static void loadTables();
++static void loadWiExt ( int, char *, struct wireless_info * );
++static void load80211Structs ( int, char *, struct wireless_info * );
++static void initStructs();
++
++// Wireless Extensions Specific Functions
++static void loadWiExtTo80211Structs ( int, char *, struct wireless_info * );
++static void displayWiExt ( struct wireless_info );
++
++// Linked List Functions
++static void addList ( char *, char *, int );
++static void initLists();                    // initialize all the linked lists
++static void flushLists();                   // flush all the linked lists
++static void flushList ( char * );           // flush a single linked list
++
++// Utility Functions
++static int  openSocket ( void );
++static int  mWatt2dbm ( int );
++static char *htob ( char * );
++static int  hasChanged ( char *, int );
++
++/****************************************************************************
++*                            Private Variables                              *
++****************************************************************************/
++static unsigned long lastLoad = 0;          // ET in secs at last table load
++
++static struct avNode *lastNode, *newNode, *np;
++
++/****************************************************************************
++*                            External Functions                             *
++****************************************************************************/
++
++/****************************************************************************
++*   ieee802dot11_variables_oid:                                             *
++*       this is the top level oid that we want to register under.  This     *
++*       is essentially a prefix, with the suffix appearing in the           *
++*       variable below.                                                     *
++****************************************************************************/
++oid ieee802dot11_variables_oid[] = { 1,2,840,10036 };
++
++/****************************************************************************
++*   variable7 ieee802dot11_variables:                                       *
++*     this variable defines function callbacks and type return information  *
++*     for the ieee802dot11 mib section                                      *
++****************************************************************************/
++struct variable7 ieee802dot11_variables[] = {
++/*  magic number        , variable type , ro/rw , callback fn  , L, oidsuffix */
++#define   DOT11STATIONID        3
++  { DOT11STATIONID      , ASN_OCTET_STR , RWRITE, var_dot11StationConfigTable, 4, { 1,1,1,1 } },
++#define   DOT11MEDIUMOCCUPANCYLIMIT  4
++  { DOT11MEDIUMOCCUPANCYLIMIT, ASN_INTEGER   , RWRITE, var_dot11StationConfigTable, 4, { 1,1,1,2 } },
++#define   DOT11CFPOLLABLE       5
++  { DOT11CFPOLLABLE     , ASN_INTEGER   , RONLY , var_dot11StationConfigTable, 4, { 1,1,1,3 } },
++#define   DOT11CFPPERIOD        6
++  { DOT11CFPPERIOD      , ASN_INTEGER   , RWRITE, var_dot11StationConfigTable, 4, { 1,1,1,4 } },
++#define   DOT11CFPMAXDURATION   7
++  { DOT11CFPMAXDURATION , ASN_INTEGER   , RWRITE, var_dot11StationConfigTable, 4, { 1,1,1,5 } },
++#define   DOT11AUTHENTICATIONRESPONSETIMEOUT  8
++  { DOT11AUTHENTICATIONRESPONSETIMEOUT, ASN_INTEGER   , RWRITE, var_dot11StationConfigTable, 4, { 1,1,1,6 } },
++#define   DOT11PRIVACYOPTIONIMPLEMENTED  9
++  { DOT11PRIVACYOPTIONIMPLEMENTED, ASN_INTEGER   , RONLY , var_dot11StationConfigTable, 4, { 1,1,1,7 } },
++#define   DOT11POWERMANAGEMENTMODE  10
++  { DOT11POWERMANAGEMENTMODE, ASN_INTEGER   , RWRITE, var_dot11StationConfigTable, 4, { 1,1,1,8 } },
++#define   DOT11DESIREDSSID      11
++  { DOT11DESIREDSSID    , ASN_OCTET_STR , RWRITE, var_dot11StationConfigTable, 4, { 1,1,1,9 } },
++#define   DOT11DESIREDBSSTYPE   12
++  { DOT11DESIREDBSSTYPE , ASN_INTEGER   , RWRITE, var_dot11StationConfigTable, 4, { 1,1,1,10 } },
++#define   DOT11OPERATIONALRATESET  13
++  { DOT11OPERATIONALRATESET, ASN_OCTET_STR , RWRITE, var_dot11StationConfigTable, 4, { 1,1,1,11 } },
++#define   DOT11BEACONPERIOD     14
++  { DOT11BEACONPERIOD   , ASN_INTEGER   , RWRITE, var_dot11StationConfigTable, 4, { 1,1,1,12 } },
++#define   DOT11DTIMPERIOD       15
++  { DOT11DTIMPERIOD     , ASN_INTEGER   , RWRITE, var_dot11StationConfigTable, 4, { 1,1,1,13 } },
++#define   DOT11ASSOCIATIONRESPONSETIMEOUT  16
++  { DOT11ASSOCIATIONRESPONSETIMEOUT, ASN_INTEGER   , RWRITE, var_dot11StationConfigTable, 4, { 1,1,1,14 } },
++#define   DOT11DISASSOCIATEREASON  17
++  { DOT11DISASSOCIATEREASON, ASN_INTEGER   , RONLY , var_dot11StationConfigTable, 4, { 1,1,1,15 } },
++#define   DOT11DISASSOCIATESTATION  18
++  { DOT11DISASSOCIATESTATION, ASN_OCTET_STR , RONLY , var_dot11StationConfigTable, 4, { 1,1,1,16 } },
++#define   DOT11DEAUTHENTICATEREASON  19
++  { DOT11DEAUTHENTICATEREASON, ASN_INTEGER   , RONLY , var_dot11StationConfigTable, 4, { 1,1,1,17 } },
++#define   DOT11DEAUTHENTICATESTATION  20
++  { DOT11DEAUTHENTICATESTATION, ASN_OCTET_STR , RONLY , var_dot11StationConfigTable, 4, { 1,1,1,18 } },
++#define   DOT11AUTHENTICATEFAILSTATUS  21
++  { DOT11AUTHENTICATEFAILSTATUS, ASN_INTEGER   , RONLY , var_dot11StationConfigTable, 4, { 1,1,1,19 } },
++#define   DOT11AUTHENTICATEFAILSTATION  22
++  { DOT11AUTHENTICATEFAILSTATION, ASN_OCTET_STR , RONLY , var_dot11StationConfigTable, 4, { 1,1,1,20 } },
++
++#define   DOT11AUTHENTICATIONALGORITHM  26
++  { DOT11AUTHENTICATIONALGORITHM, ASN_INTEGER   , RONLY , var_dot11AuthenticationAlgorithmsTable, 4, { 1,2,1,2 } },
++#define   DOT11AUTHENTICATIONALGORITHMSENABLE  27
++  { DOT11AUTHENTICATIONALGORITHMSENABLE, ASN_INTEGER   , RWRITE, var_dot11AuthenticationAlgorithmsTable, 4, { 1,2,1,3 } },
++
++#define   DOT11WEPDEFAULTKEYVALUE  31
++  { DOT11WEPDEFAULTKEYVALUE, ASN_OCTET_STR , RWRITE, var_dot11WEPDefaultKeysTable, 4, { 1,3,1,2 } },
++
++#define   DOT11WEPKEYMAPPINGADDRESS  35
++  { DOT11WEPKEYMAPPINGADDRESS, ASN_OCTET_STR , RWRITE, var_dot11WEPKeyMappingsTable, 4, { 1,4,1,2 } },
++#define   DOT11WEPKEYMAPPINGWEPON  36
++  { DOT11WEPKEYMAPPINGWEPON, ASN_INTEGER   , RWRITE, var_dot11WEPKeyMappingsTable, 4, { 1,4,1,3 } },
++#define   DOT11WEPKEYMAPPINGVALUE  37
++  { DOT11WEPKEYMAPPINGVALUE, ASN_OCTET_STR , RWRITE, var_dot11WEPKeyMappingsTable, 4, { 1,4,1,4 } },
++#define   DOT11WEPKEYMAPPINGSTATUS  38
++  { DOT11WEPKEYMAPPINGSTATUS, ASN_INTEGER   , RWRITE, var_dot11WEPKeyMappingsTable, 4, { 1,4,1,5 } },
++
++#define   DOT11PRIVACYINVOKED   41
++  { DOT11PRIVACYINVOKED , ASN_INTEGER   , RWRITE, var_dot11PrivacyTable, 4, { 1,5,1,1 } },
++#define   DOT11WEPDEFAULTKEYID  42
++  { DOT11WEPDEFAULTKEYID, ASN_INTEGER   , RWRITE, var_dot11PrivacyTable, 4, { 1,5,1,2 } },
++#define   DOT11WEPKEYMAPPINGLENGTH  43
++  { DOT11WEPKEYMAPPINGLENGTH, ASN_INTEGER   , RWRITE, var_dot11PrivacyTable, 4, { 1,5,1,3 } },
++#define   DOT11EXCLUDEUNENCRYPTED  44
++  { DOT11EXCLUDEUNENCRYPTED, ASN_INTEGER   , RWRITE, var_dot11PrivacyTable, 4, { 1,5,1,4 } },
++#define   DOT11WEPICVERRORCOUNT  45
++  { DOT11WEPICVERRORCOUNT, ASN_COUNTER   , RONLY , var_dot11PrivacyTable, 4, { 1,5,1,5 } },
++#define   DOT11WEPEXCLUDEDCOUNT  46
++  { DOT11WEPEXCLUDEDCOUNT, ASN_COUNTER   , RONLY , var_dot11PrivacyTable, 4, { 1,5,1,6 } },
++
++#define   DOT11MACADDRESS       49
++  { DOT11MACADDRESS     , ASN_OCTET_STR , RONLY , var_dot11OperationTable, 4, { 2,1,1,1 } },
++#define   DOT11RTSTHRESHOLD     50
++  { DOT11RTSTHRESHOLD   , ASN_INTEGER   , RWRITE, var_dot11OperationTable, 4, { 2,1,1,2 } },
++#define   DOT11SHORTRETRYLIMIT  51
++  { DOT11SHORTRETRYLIMIT, ASN_INTEGER   , RWRITE, var_dot11OperationTable, 4, { 2,1,1,3 } },
++#define   DOT11LONGRETRYLIMIT   52
++  { DOT11LONGRETRYLIMIT , ASN_INTEGER   , RWRITE, var_dot11OperationTable, 4, { 2,1,1,4 } },
++#define   DOT11FRAGMENTATIONTHRESHOLD  53
++  { DOT11FRAGMENTATIONTHRESHOLD, ASN_INTEGER   , RWRITE, var_dot11OperationTable, 4, { 2,1,1,5 } },
++#define   DOT11MAXTRANSMITMSDULIFETIME  54
++  { DOT11MAXTRANSMITMSDULIFETIME, ASN_INTEGER   , RWRITE, var_dot11OperationTable, 4, { 2,1,1,6 } },
++#define   DOT11MAXRECEIVELIFETIME  55
++  { DOT11MAXRECEIVELIFETIME, ASN_INTEGER   , RWRITE, var_dot11OperationTable, 4, { 2,1,1,7 } },
++#define   DOT11MANUFACTURERID   56
++  { DOT11MANUFACTURERID , ASN_OCTET_STR , RONLY , var_dot11OperationTable, 4, { 2,1,1,8 } },
++#define   DOT11PRODUCTID        57
++  { DOT11PRODUCTID      , ASN_OCTET_STR , RONLY , var_dot11OperationTable, 4, { 2,1,1,9 } },
++
++#define   DOT11TRANSMITTEDFRAGMENTCOUNT  60
++  { DOT11TRANSMITTEDFRAGMENTCOUNT, ASN_COUNTER   , RONLY , var_dot11CountersTable, 4, { 2,2,1,1 } },
++#define   DOT11MULTICASTTRANSMITTEDFRAMECOUNT  61
++  { DOT11MULTICASTTRANSMITTEDFRAMECOUNT, ASN_COUNTER   , RONLY , var_dot11CountersTable, 4, { 2,2,1,2 } },
++#define   DOT11FAILEDCOUNT      62
++  { DOT11FAILEDCOUNT    , ASN_COUNTER   , RONLY , var_dot11CountersTable, 4, { 2,2,1,3 } },
++#define   DOT11RETRYCOUNT       63
++  { DOT11RETRYCOUNT     , ASN_COUNTER   , RONLY , var_dot11CountersTable, 4, { 2,2,1,4 } },
++#define   DOT11MULTIPLERETRYCOUNT  64
++  { DOT11MULTIPLERETRYCOUNT, ASN_COUNTER   , RONLY , var_dot11CountersTable, 4, { 2,2,1,5 } },
++#define   DOT11FRAMEDUPLICATECOUNT  65
++  { DOT11FRAMEDUPLICATECOUNT, ASN_COUNTER   , RONLY , var_dot11CountersTable, 4, { 2,2,1,6 } },
++#define   DOT11RTSSUCCESSCOUNT  66
++  { DOT11RTSSUCCESSCOUNT, ASN_COUNTER   , RONLY , var_dot11CountersTable, 4, { 2,2,1,7 } },
++#define   DOT11RTSFAILURECOUNT  67
++  { DOT11RTSFAILURECOUNT, ASN_COUNTER   , RONLY , var_dot11CountersTable, 4, { 2,2,1,8 } },
++#define   DOT11ACKFAILURECOUNT  68
++  { DOT11ACKFAILURECOUNT, ASN_COUNTER   , RONLY , var_dot11CountersTable, 4, { 2,2,1,9 } },
++#define   DOT11RECEIVEDFRAGMENTCOUNT  69
++  { DOT11RECEIVEDFRAGMENTCOUNT, ASN_COUNTER   , RONLY , var_dot11CountersTable, 4, { 2,2,1,10 } },
++#define   DOT11MULTICASTRECEIVEDFRAMECOUNT  70
++  { DOT11MULTICASTRECEIVEDFRAMECOUNT, ASN_COUNTER   , RONLY , var_dot11CountersTable, 4, { 2,2,1,11 } },
++#define   DOT11FCSERRORCOUNT    71
++  { DOT11FCSERRORCOUNT  , ASN_COUNTER   , RONLY , var_dot11CountersTable, 4, { 2,2,1,12 } },
++#define   DOT11TRANSMITTEDFRAMECOUNT  72
++  { DOT11TRANSMITTEDFRAMECOUNT, ASN_COUNTER   , RONLY , var_dot11CountersTable, 4, { 2,2,1,13 } },
++#define   DOT11WEPUNDECRYPTABLECOUNT  73
++  { DOT11WEPUNDECRYPTABLECOUNT, ASN_COUNTER   , RONLY , var_dot11CountersTable, 4, { 2,2,1,14 } },
++
++#define   DOT11ADDRESS          77
++  { DOT11ADDRESS        , ASN_OCTET_STR , RWRITE, var_dot11GroupAddressesTable, 4, { 2,3,1,2 } },
++#define   DOT11GROUPADDRESSESSTATUS  78
++  { DOT11GROUPADDRESSESSTATUS, ASN_INTEGER   , RWRITE, var_dot11GroupAddressesTable, 4, { 2,3,1,3 } },
++
++#define   DOT11RESOURCETYPEIDNAME  79
++  { DOT11RESOURCETYPEIDNAME, ASN_OCTET_STR , RONLY , var_ieee802dot11, 3, { 3,1,1 } },
++#define   DOT11MANUFACTUREROUI  82
++  { DOT11MANUFACTUREROUI, ASN_OCTET_STR , RONLY , var_dot11ResourceInfoTable, 5, { 3,1,2,1,1 } },
++#define   DOT11MANUFACTURERNAME  83
++  { DOT11MANUFACTURERNAME, ASN_OCTET_STR , RONLY , var_dot11ResourceInfoTable, 5, { 3,1,2,1,2 } },
++#define   DOT11MANUFACTURERPRODUCTNAME  84
++  { DOT11MANUFACTURERPRODUCTNAME, ASN_OCTET_STR , RONLY , var_dot11ResourceInfoTable, 5, { 3,1,2,1,3 } },
++#define   DOT11MANUFACTURERPRODUCTVERSION  85
++  { DOT11MANUFACTURERPRODUCTVERSION, ASN_OCTET_STR , RONLY , var_dot11ResourceInfoTable, 5, { 3,1,2,1,4 } },
++
++#define   DOT11PHYTYPE          88
++  { DOT11PHYTYPE        , ASN_INTEGER   , RONLY , var_dot11PhyOperationTable, 4, { 4,1,1,1 } },
++#define   DOT11CURRENTREGDOMAIN  89
++  { DOT11CURRENTREGDOMAIN, ASN_INTEGER   , RWRITE, var_dot11PhyOperationTable, 4, { 4,1,1,2 } },
++#define   DOT11TEMPTYPE         90
++  { DOT11TEMPTYPE       , ASN_INTEGER   , RONLY , var_dot11PhyOperationTable, 4, { 4,1,1,3 } },
++#define   DOT11CURRENTTXANTENNA  93
++  { DOT11CURRENTTXANTENNA, ASN_INTEGER   , RWRITE, var_dot11PhyAntennaTable, 4, { 4,2,1,1 } },
++#define   DOT11DIVERSITYSUPPORT  94
++  { DOT11DIVERSITYSUPPORT, ASN_INTEGER   , RONLY , var_dot11PhyAntennaTable, 4, { 4,2,1,2 } },
++#define   DOT11CURRENTRXANTENNA  95
++  { DOT11CURRENTRXANTENNA, ASN_INTEGER   , RWRITE, var_dot11PhyAntennaTable, 4, { 4,2,1,3 } },
++#define   DOT11NUMBERSUPPORTEDPOWERLEVELS  98
++  { DOT11NUMBERSUPPORTEDPOWERLEVELS, ASN_INTEGER   , RONLY , var_dot11PhyTxPowerTable, 4, { 4,3,1,1 } },
++#define   DOT11TXPOWERLEVEL1    99
++  { DOT11TXPOWERLEVEL1  , ASN_INTEGER   , RONLY , var_dot11PhyTxPowerTable, 4, { 4,3,1,2 } },
++#define   DOT11TXPOWERLEVEL2    100
++  { DOT11TXPOWERLEVEL2  , ASN_INTEGER   , RONLY , var_dot11PhyTxPowerTable, 4, { 4,3,1,3 } },
++#define   DOT11TXPOWERLEVEL3    101
++  { DOT11TXPOWERLEVEL3  , ASN_INTEGER   , RONLY , var_dot11PhyTxPowerTable, 4, { 4,3,1,4 } },
++#define   DOT11TXPOWERLEVEL4    102
++  { DOT11TXPOWERLEVEL4  , ASN_INTEGER   , RONLY , var_dot11PhyTxPowerTable, 4, { 4,3,1,5 } },
++#define   DOT11TXPOWERLEVEL5    103
++  { DOT11TXPOWERLEVEL5  , ASN_INTEGER   , RONLY , var_dot11PhyTxPowerTable, 4, { 4,3,1,6 } },
++#define   DOT11TXPOWERLEVEL6    104
++  { DOT11TXPOWERLEVEL6  , ASN_INTEGER   , RONLY , var_dot11PhyTxPowerTable, 4, { 4,3,1,7 } },
++#define   DOT11TXPOWERLEVEL7    105
++  { DOT11TXPOWERLEVEL7  , ASN_INTEGER   , RONLY , var_dot11PhyTxPowerTable, 4, { 4,3,1,8 } },
++#define   DOT11TXPOWERLEVEL8    106
++  { DOT11TXPOWERLEVEL8  , ASN_INTEGER   , RONLY , var_dot11PhyTxPowerTable, 4, { 4,3,1,9 } },
++#define   DOT11CURRENTTXPOWERLEVEL  107
++  { DOT11CURRENTTXPOWERLEVEL, ASN_INTEGER   , RWRITE, var_dot11PhyTxPowerTable, 4, { 4,3,1,10 } },
++
++#define   DOT11HOPTIME          110
++  { DOT11HOPTIME        , ASN_INTEGER   , RONLY , var_dot11PhyFHSSTable, 4, { 4,4,1,1 } },
++#define   DOT11CURRENTCHANNELNUMBER  111
++  { DOT11CURRENTCHANNELNUMBER, ASN_INTEGER   , RWRITE, var_dot11PhyFHSSTable, 4, { 4,4,1,2 } },
++#define   DOT11MAXDWELLTIME     112
++  { DOT11MAXDWELLTIME   , ASN_INTEGER   , RONLY , var_dot11PhyFHSSTable, 4, { 4,4,1,3 } },
++#define   DOT11CURRENTDWELLTIME  113
++  { DOT11CURRENTDWELLTIME, ASN_INTEGER   , RWRITE, var_dot11PhyFHSSTable, 4, { 4,4,1,4 } },
++#define   DOT11CURRENTSET       114
++  { DOT11CURRENTSET     , ASN_INTEGER   , RWRITE, var_dot11PhyFHSSTable, 4, { 4,4,1,5 } },
++#define   DOT11CURRENTPATTERN   115
++  { DOT11CURRENTPATTERN , ASN_INTEGER   , RWRITE, var_dot11PhyFHSSTable, 4, { 4,4,1,6 } },
++#define   DOT11CURRENTINDEX     116
++  { DOT11CURRENTINDEX   , ASN_INTEGER   , RWRITE, var_dot11PhyFHSSTable, 4, { 4,4,1,7 } },
++
++#define   DOT11CURRENTCHANNEL   119
++  { DOT11CURRENTCHANNEL , ASN_INTEGER   , RWRITE, var_dot11PhyDSSSTable, 4, { 4,5,1,1 } },
++#define   DOT11CCAMODESUPPORTED  120
++  { DOT11CCAMODESUPPORTED, ASN_INTEGER   , RONLY , var_dot11PhyDSSSTable, 4, { 4,5,1,2 } },
++#define   DOT11CURRENTCCAMODE   121
++  { DOT11CURRENTCCAMODE , ASN_INTEGER   , RWRITE, var_dot11PhyDSSSTable, 4, { 4,5,1,3 } },
++#define   DOT11EDTHRESHOLD      122
++  { DOT11EDTHRESHOLD    , ASN_INTEGER   , RWRITE, var_dot11PhyDSSSTable, 4, { 4,5,1,4 } },
++
++#define   DOT11CCAWATCHDOGTIMERMAX  125
++  { DOT11CCAWATCHDOGTIMERMAX, ASN_INTEGER   , RWRITE, var_dot11PhyIRTable, 4, { 4,6,1,1 } },
++#define   DOT11CCAWATCHDOGCOUNTMAX  126
++  { DOT11CCAWATCHDOGCOUNTMAX, ASN_INTEGER   , RWRITE, var_dot11PhyIRTable, 4, { 4,6,1,2 } },
++#define   DOT11CCAWATCHDOGTIMERMIN  127
++  { DOT11CCAWATCHDOGTIMERMIN, ASN_INTEGER   , RWRITE, var_dot11PhyIRTable, 4, { 4,6,1,3 } },
++#define   DOT11CCAWATCHDOGCOUNTMIN  128
++  { DOT11CCAWATCHDOGCOUNTMIN, ASN_INTEGER   , RWRITE, var_dot11PhyIRTable, 4, { 4,6,1,4 } },
++
++#define   DOT11REGDOMAINSSUPPORTVALUE  132
++  { DOT11REGDOMAINSSUPPORTVALUE, ASN_INTEGER   , RONLY , var_dot11RegDomainsSupportedTable, 4, { 4,7,1,2 } },
++
++#define   DOT11SUPPORTEDTXANTENNA  136
++  { DOT11SUPPORTEDTXANTENNA, ASN_INTEGER   , RWRITE, var_dot11AntennasListTable, 4, { 4,8,1,2 } },
++#define   DOT11SUPPORTEDRXANTENNA  137
++  { DOT11SUPPORTEDRXANTENNA, ASN_INTEGER   , RWRITE, var_dot11AntennasListTable, 4, { 4,8,1,3 } },
++#define   DOT11DIVERSITYSELECTIONRX  138
++  { DOT11DIVERSITYSELECTIONRX, ASN_INTEGER   , RWRITE, var_dot11AntennasListTable, 4, { 4,8,1,4 } },
++
++#define   DOT11SUPPORTEDDATARATESTXVALUE  142
++  { DOT11SUPPORTEDDATARATESTXVALUE, ASN_INTEGER   , RONLY , var_dot11SupportedDataRatesTxTable, 4, { 4,9,1,2 } },
++
++#define   DOT11SUPPORTEDDATARATESRXVALUE  146
++  { DOT11SUPPORTEDDATARATESRXVALUE, ASN_INTEGER   , RONLY , var_dot11SupportedDataRatesRxTable, 4, { 4,10,1,2 } },
++};
++// ( L = length of the oidsuffix )
++
++/****************************************************************************
++*                                                                           *
++*         init_ieee802dot11() - perform any required initialization         *
++*                                                                           *
++****************************************************************************/
++void init_ieee802dot11 ( void ) {
++
++  /* register ourselves with the agent to handle our mib tree */
++  REGISTER_MIB("ieee802dot11", ieee802dot11_variables, variable7,
++               ieee802dot11_variables_oid);
++
++  initLists();
++}
++
++/****************************************************************************
++*                                                                           *
++*    shutdown_ieee802dot11() - perform any required cleanup @ shutdown      *
++*                                                                           *
++****************************************************************************/
++void shutdown_ieee802dot11 ( void )
++{
++  flushLists();
++}
++
++/****************************************************************************
++*                                                                           *
++*   var_ieee802dot11() -                                                    *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_ieee802dot11 ( struct variable *vp, 
++                    oid     *name, 
++                    size_t  *length, 
++                    int     exact, 
++                    size_t  *var_len, 
++                    WriteMethod **write_method)
++{
++  loadTables();                                               
++
++  if ( header_generic ( vp, name, length, exact,var_len,write_method )
++                                  == MATCH_FAILED )
++    return NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11RESOURCETYPEIDNAME:
++      if ( !haveResourceTypeIDName )
++        return NULL;
++      *var_len = strlen ( resourceTypeIDName );
++      return ( UCHAR * ) resourceTypeIDName;
++
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*  var_dot11StationConfigTable() - return a variable value from the table   *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11StationConfigTable ( struct variable *vp,
++                              oid     *name,
++                              size_t  *length,
++                              int     exact,
++                              size_t  *var_len,
++                              WriteMethod **write_method )
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++  static char MACWork[17];
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &scList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    sc = ( struct scTbl_data * ) np->data;
++    rName[vp->namelen] = sc->ifIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) == 0 )) || 
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) >  0 ))) {
++
++      switch ( vp->magic ) {      // found requested OID, now check for requested variable
++        case DOT11STATIONID: 
++          if ( sc->haveStationID                     ) found = TRUE; break;
++        case DOT11MEDIUMOCCUPANCYLIMIT:
++          if ( sc->haveMediumOccupancyLimit          ) found = TRUE; break;
++        case DOT11CFPOLLABLE:
++          if ( sc->haveCFPPollable                   ) found = TRUE; break;
++        case DOT11CFPPERIOD:
++          if ( sc->haveCFPPeriod                     ) found = TRUE; break;
++        case DOT11CFPMAXDURATION:
++          if ( sc->haveMaxDuration                   ) found = TRUE; break;
++        case DOT11AUTHENTICATIONRESPONSETIMEOUT:
++          if ( sc->haveAuthenticationResponseTimeOut ) found = TRUE; break;
++        case DOT11PRIVACYOPTIONIMPLEMENTED:
++          if ( sc->havePrivacyOptionImplemented      ) found = TRUE; break;
++        case DOT11POWERMANAGEMENTMODE:
++          if ( sc->havePowerManagementMode           ) found = TRUE; break;
++        case DOT11DESIREDSSID:
++          if ( sc->haveDesiredSSID                   ) found = TRUE; break;
++        case DOT11DESIREDBSSTYPE:
++          if ( sc->haveDesiredBSSType                ) found = TRUE; break;
++        case DOT11OPERATIONALRATESET:
++          if ( sc->haveOperationalRateSet            ) found = TRUE; break;
++        case DOT11BEACONPERIOD: 
++          if ( sc->haveBeaconPeriod                  ) found = TRUE; break;
++        case DOT11DTIMPERIOD:
++          if ( sc->haveDTIMPeriod                    ) found = TRUE; break;
++        case DOT11ASSOCIATIONRESPONSETIMEOUT:
++          if ( sc->haveAssociationResponseTimeOut    ) found = TRUE; break;
++        case DOT11DISASSOCIATEREASON:
++          if ( sc->disAssociationReason              ) found = TRUE; break;
++        case DOT11DISASSOCIATESTATION:
++          if ( sc->haveDisAssociationStation         ) found = TRUE; break;
++        case DOT11DEAUTHENTICATEREASON:
++          if ( sc->deAuthenticationReason            ) found = TRUE; break;
++        case DOT11DEAUTHENTICATESTATION:
++          if ( sc->haveDeAuthenticationStation       ) found = TRUE; break;
++        case DOT11AUTHENTICATEFAILSTATUS:
++          if ( sc->authenticateFailStatus            ) found = TRUE; break;
++        case DOT11AUTHENTICATEFAILSTATION:
++          if ( sc->haveAuthenticateFailStation       ) found = TRUE; break;
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 1 ) * sizeof ( oid ));
++  *length = vp->namelen + 1;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11STATIONID: 
++//    *write_method = write_dot11StationID;
++      MACWork[ 0] = sc->stationID [ 0];
++      MACWork[ 1] = sc->stationID [ 1];
++      MACWork[ 2] = sc->stationID [ 3];
++      MACWork[ 3] = sc->stationID [ 4];
++      MACWork[ 4] = sc->stationID [ 6];
++      MACWork[ 5] = sc->stationID [ 7];
++      MACWork[ 6] = sc->stationID [ 9];
++      MACWork[ 7] = sc->stationID [10];
++      MACWork[ 8] = sc->stationID [12];
++      MACWork[ 9] = sc->stationID [13];
++      MACWork[10] = sc->stationID [15];
++      MACWork[11] = sc->stationID [16];
++      MACWork[12] = '\0';
++      *var_len = 6;
++      return ( UCHAR * ) htob ( MACWork );
++
++    case DOT11MEDIUMOCCUPANCYLIMIT:
++//    *write_method = write_dot11MediumOccupancyLimit;
++      sc->mediumOccupancyLimit = 5;
++      return ( UCHAR * ) &sc->mediumOccupancyLimit;
++
++    case DOT11CFPOLLABLE:
++      return ( UCHAR * ) &sc->CFPPollable;
++
++    case DOT11CFPPERIOD:
++//    *write_method = write_dot11CFPPeriod;
++      return ( UCHAR * ) &sc->CFPPeriod;
++
++    case DOT11CFPMAXDURATION:
++//    *write_method = write_dot11CFPMaxDuration;
++      return ( UCHAR * ) &sc->maxDuration;
++
++    case DOT11AUTHENTICATIONRESPONSETIMEOUT:
++//    *write_method = write_dot11AuthenticationResponseTimeOut;
++      return ( UCHAR * ) &sc->authenticationResponseTimeOut;
++
++    case DOT11PRIVACYOPTIONIMPLEMENTED:
++      return ( UCHAR * ) &sc->privacyOptionImplemented;
++
++    case DOT11POWERMANAGEMENTMODE:
++//    *write_method = write_dot11PowerManagementMode;
++      return ( UCHAR * ) &sc->powerManagementMode;
++
++    case DOT11DESIREDSSID:
++//    *write_method = write_dot11DesiredSSID;
++      *var_len = strlen ( sc->desiredSSID );
++      return ( UCHAR * ) sc->desiredSSID;
++
++    case DOT11DESIREDBSSTYPE:
++//    *write_method = write_dot11DesiredBSSType;
++      return ( UCHAR * ) &sc->desiredBSSType;
++
++    case DOT11OPERATIONALRATESET:
++//    *write_method = write_dot11OperationalRateSet;
++      *var_len = strlen ( sc->operationalRateSet );
++      return ( UCHAR * ) sc->operationalRateSet;
++
++    case DOT11BEACONPERIOD: 
++//    *write_method = write_dot11BeaconPeriod;
++      return ( UCHAR * ) &sc->beaconPeriod;
++
++    case DOT11DTIMPERIOD:
++//    *write_method = write_dot11DTIMPeriod;
++      return ( UCHAR * ) &sc->DTIMPeriod;
++
++    case DOT11ASSOCIATIONRESPONSETIMEOUT:
++//    *write_method = write_dot11AssociationResponseTimeOut;
++      return ( UCHAR * ) &sc->associationResponseTimeOut;
++
++    case DOT11DISASSOCIATEREASON:
++      return ( UCHAR * ) &sc->disAssociationReason;
++
++    case DOT11DISASSOCIATESTATION:
++      MACWork[ 0] = sc->disAssociationStation[ 0];
++      MACWork[ 1] = sc->disAssociationStation[ 1];
++      MACWork[ 2] = sc->disAssociationStation[ 3];
++      MACWork[ 3] = sc->disAssociationStation[ 4];
++      MACWork[ 4] = sc->disAssociationStation[ 6];
++      MACWork[ 5] = sc->disAssociationStation[ 7];
++      MACWork[ 6] = sc->disAssociationStation[ 9];
++      MACWork[ 7] = sc->disAssociationStation[10];
++      MACWork[ 8] = sc->disAssociationStation[12];
++      MACWork[ 9] = sc->disAssociationStation[13];
++      MACWork[10] = sc->disAssociationStation[15];
++      MACWork[11] = sc->disAssociationStation[16];
++      MACWork[12] = '\0';
++      *var_len = 6;
++      return ( UCHAR * ) htob ( MACWork );
++
++    case DOT11DEAUTHENTICATEREASON:
++      return ( UCHAR * ) &sc->deAuthenticationReason;
++
++    case DOT11DEAUTHENTICATESTATION:
++      MACWork[ 0] = sc->deAuthenticationStation[ 0];
++      MACWork[ 1] = sc->deAuthenticationStation[ 1];
++      MACWork[ 2] = sc->deAuthenticationStation[ 3];
++      MACWork[ 3] = sc->deAuthenticationStation[ 4];
++      MACWork[ 4] = sc->deAuthenticationStation[ 6];
++      MACWork[ 5] = sc->deAuthenticationStation[ 7];
++      MACWork[ 6] = sc->deAuthenticationStation[ 9];
++      MACWork[ 7] = sc->deAuthenticationStation[10];
++      MACWork[ 8] = sc->deAuthenticationStation[12];
++      MACWork[ 9] = sc->deAuthenticationStation[13];
++      MACWork[10] = sc->deAuthenticationStation[15];
++      MACWork[11] = sc->deAuthenticationStation[16];
++      MACWork[12] = '\0';
++      *var_len = 6;
++      return ( UCHAR * ) htob ( MACWork );
++
++    case DOT11AUTHENTICATEFAILSTATUS:
++      return ( UCHAR * ) &sc->authenticateFailStatus;
++
++    case DOT11AUTHENTICATEFAILSTATION:
++      MACWork[ 0] = sc->authenticateFailStation[ 0];
++      MACWork[ 1] = sc->authenticateFailStation[ 1];
++      MACWork[ 2] = sc->authenticateFailStation[ 3];
++      MACWork[ 3] = sc->authenticateFailStation[ 4];
++      MACWork[ 4] = sc->authenticateFailStation[ 6];
++      MACWork[ 5] = sc->authenticateFailStation[ 7];
++      MACWork[ 6] = sc->authenticateFailStation[ 9];
++      MACWork[ 7] = sc->authenticateFailStation[10];
++      MACWork[ 8] = sc->authenticateFailStation[12];
++      MACWork[ 9] = sc->authenticateFailStation[13];
++      MACWork[10] = sc->authenticateFailStation[15];
++      MACWork[11] = sc->authenticateFailStation[16];
++      MACWork[12] = '\0';
++      *var_len = 6;
++      return ( UCHAR * ) htob ( MACWork );
++
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*  var_dot11AuthenticationAlgorithmsTable() -                               *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11AuthenticationAlgorithmsTable (  struct variable *vp,
++                                          oid     *name,
++                                          size_t  *length,
++                                          int     exact,
++                                          size_t  *var_len,
++                                          WriteMethod **write_method )
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &aaList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    aa = ( struct aaTbl_data * ) np->data;
++    rName[vp->namelen + 0] = aa->ifIndex;
++    rName[vp->namelen + 1] = aa->authenticationAlgorithmsIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11AUTHENTICATIONALGORITHM:
++          if ( aa->haveAuthenticationAlgorithm    ) found = TRUE; break;
++        case DOT11AUTHENTICATIONALGORITHMSENABLE:
++          if ( aa->authenticationAlgorithmsEnable ) found = TRUE; break;
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 2 ) * sizeof ( oid ));
++  *length = vp->namelen + 2;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11AUTHENTICATIONALGORITHM:
++      return ( UCHAR * ) &aa->authenticationAlgorithm;
++        
++    case DOT11AUTHENTICATIONALGORITHMSENABLE:
++//    *write_method = write_dot11AuthenticationAlgorithmsEnable;
++      return ( UCHAR * ) &aa->authenticationAlgorithmsEnable;
++
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*  var_dot11WEPDefaultKeysTable() -                                         *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11WEPDefaultKeysTable ( struct variable *vp,
++                                oid     *name,
++                                size_t  *length,
++                                int     exact,
++                                size_t  *var_len,
++                                WriteMethod **write_method )
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &dfList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    df = ( struct dfTbl_data * ) np->data;
++    rName[vp->namelen + 0] = df->ifIndex;
++    rName[vp->namelen + 1] = df->WEPDefaultKeyIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11WEPDEFAULTKEYVALUE:
++          if ( df->haveWEPDefaultKeyValue ) found = TRUE; break;
++      }          
++    }          
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 2 ) * sizeof ( oid ));
++  *length = vp->namelen + 2;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11WEPDEFAULTKEYVALUE:
++//    *write_method = write_dot11WEPDefaultKeyValue;
++      *var_len = strlen ( df->WEPDefaultKeyValue );
++      return ( UCHAR * ) df->WEPDefaultKeyValue;
++
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*  var_dot11WEPKeyMappingsTable() -                                         *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11WEPKeyMappingsTable ( struct variable *vp,
++                                oid     *name,
++                                size_t  *length,
++                                int     exact,
++                                size_t  *var_len,
++                                WriteMethod **write_method)
++{
++  static char MACWork[17];
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &kmList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    km = ( struct kmTbl_data * ) np->data;
++    rName[vp->namelen + 0] = km->ifIndex;
++    rName[vp->namelen + 1] = km->WEPKeyMappingIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11WEPKEYMAPPINGADDRESS:
++          if ( km->haveWEPKeyMappingAddress ) found = TRUE; break;
++        case DOT11WEPKEYMAPPINGWEPON:
++          if ( km->haveWEPKeyMappingWEPOn   ) found = TRUE; break;
++        case DOT11WEPKEYMAPPINGVALUE:
++          if ( km->haveWEPKeyMappingValue   ) found = TRUE; break;
++        case DOT11WEPKEYMAPPINGSTATUS:
++          if ( km->haveWEPKeyMappingStatus  ) found = TRUE; break; 
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 2 ) * sizeof ( oid ));
++  *length = vp->namelen + 2;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11WEPKEYMAPPINGADDRESS:
++//    *write_method = write_dot11WEPKeyMappingAddress;
++      MACWork[ 0] = km->WEPKeyMappingAddress[ 0];
++      MACWork[ 1] = km->WEPKeyMappingAddress[ 1];
++      MACWork[ 2] = km->WEPKeyMappingAddress[ 3];
++      MACWork[ 3] = km->WEPKeyMappingAddress[ 4];
++      MACWork[ 4] = km->WEPKeyMappingAddress[ 6];
++      MACWork[ 5] = km->WEPKeyMappingAddress[ 7];
++      MACWork[ 6] = km->WEPKeyMappingAddress[ 9];
++      MACWork[ 7] = km->WEPKeyMappingAddress[10];
++      MACWork[ 8] = km->WEPKeyMappingAddress[12];
++      MACWork[ 9] = km->WEPKeyMappingAddress[13];
++      MACWork[10] = km->WEPKeyMappingAddress[15];
++      MACWork[11] = km->WEPKeyMappingAddress[16];
++      MACWork[12] = '\0';
++      *var_len = 6;
++      return ( UCHAR * ) htob ( MACWork );
++
++    case DOT11WEPKEYMAPPINGWEPON:
++//    *write_method = write_dot11WEPKeyMappingWEPOn;
++      return ( UCHAR * ) &km->WEPKeyMappingWEPOn;
++
++    case DOT11WEPKEYMAPPINGVALUE:
++//    *write_method = write_dot11WEPKeyMappingValue;
++      *var_len = strlen ( km->WEPKeyMappingValue );
++      return ( UCHAR * ) km->WEPKeyMappingValue;
++
++    case DOT11WEPKEYMAPPINGSTATUS:
++//    *write_method = write_dot11WEPKeyMappingStatus;
++      return ( UCHAR * ) &km->WEPKeyMappingStatus;
++
++    default:
++      ERROR_MSG ( "" );
++  }
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*   var_dot11PrivacyTable() -                                               *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11PrivacyTable ( struct variable *vp,
++                        oid     *name,
++                        size_t  *length,
++                        int     exact,
++                        size_t  *var_len,
++                        WriteMethod **write_method )
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &prList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    pr = ( struct prTbl_data * ) np->data;
++    rName[vp->namelen] = pr->ifIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11PRIVACYINVOKED:
++          if ( pr->havePrivacyInvoked      ) found = TRUE; break;
++        case DOT11WEPDEFAULTKEYID:
++          if ( pr->haveWEPDefaultKeyID     ) found = TRUE; break;
++        case DOT11WEPKEYMAPPINGLENGTH:
++          if ( pr->haveWEPKeyMappingLength ) found = TRUE; break;
++        case DOT11EXCLUDEUNENCRYPTED:
++          if ( pr->haveExcludeUnencrypted  ) found = TRUE; break;
++        case DOT11WEPICVERRORCOUNT:
++          if ( pr->haveWEPICVErrorCount    ) found = TRUE; break;
++        case DOT11WEPEXCLUDEDCOUNT:
++          if ( pr->haveWEPExcludedCount    ) found = TRUE; break;
++      }      
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 1 ) * sizeof ( oid ));
++  *length = vp->namelen + 1;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11PRIVACYINVOKED:
++//    *write_method = write_dot11PrivacyInvoked;
++      return ( UCHAR * ) &pr->privacyInvoked;
++
++    case DOT11WEPDEFAULTKEYID:
++//    *write_method = write_dot11WEPDefaultKeyID;
++      return ( UCHAR * ) &pr->WEPDefaultKeyID;
++
++    case DOT11WEPKEYMAPPINGLENGTH:
++//    *write_method = write_dot11WEPKeyMappingLength;
++      return ( UCHAR * ) &pr->WEPKeyMappingLength;
++
++    case DOT11EXCLUDEUNENCRYPTED:
++//    *write_method = write_dot11ExcludeUnencrypted;
++      return ( UCHAR * ) &pr->excludeUnencrypted;
++
++    case DOT11WEPICVERRORCOUNT:
++      return ( UCHAR * ) &pr->WEPICVErrorCount;
++        
++    case DOT11WEPEXCLUDEDCOUNT:
++      return ( UCHAR * ) &pr->WEPExcludedCount;
++        
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*   var_dot11OperationTable() -                                             *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11OperationTable ( struct variable *vp,
++                          oid     *name,
++                          size_t  *length,
++                          int     exact,
++                          size_t  *var_len,
++                          WriteMethod **write_method )
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++  static char MACWork[17];
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &opList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    op = ( struct opTbl_data * ) np->data;
++    rName[vp->namelen] = op->ifIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) >  0 ))) {
++
++      switch ( vp->magic ) {      // found requested OID, now check for requested variable
++        case DOT11MACADDRESS:             
++          if ( op->haveMACAddress              ) found = TRUE; break;
++        case DOT11RTSTHRESHOLD:           
++          if ( op->haveRTSThreshold            ) found = TRUE; break;
++        case DOT11SHORTRETRYLIMIT: 
++          if ( op->haveShortRetryLimit         ) found = TRUE; break;
++        case DOT11LONGRETRYLIMIT:
++          if ( op->haveLongRetryLimit          ) found = TRUE; break;
++        case DOT11FRAGMENTATIONTHRESHOLD: 
++          if ( op->haveFragmentationThreshold  ) found = TRUE; break;
++        case DOT11MAXTRANSMITMSDULIFETIME: 
++          if ( op->haveMaxTransmitMSDULifetime ) found = TRUE; break;
++        case DOT11MAXRECEIVELIFETIME:
++          if ( op->haveMaxReceiveLifetime      ) found = TRUE; break;
++        case DOT11MANUFACTURERID:
++          if ( op->haveManufacturerID          ) found = TRUE; break;
++        case DOT11PRODUCTID:
++          if ( op->haveProductID               ) found = TRUE; break;
++      }
++    }
++    if ( found ) 
++      break;
++  }
++
++  if ( !found )
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 1 ) * sizeof ( oid ));
++  *length = vp->namelen + 1;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11MACADDRESS:
++      MACWork[ 0] = op->MACAddress[ 0];
++      MACWork[ 1] = op->MACAddress[ 1];
++      MACWork[ 2] = op->MACAddress[ 3];
++      MACWork[ 3] = op->MACAddress[ 4];
++      MACWork[ 4] = op->MACAddress[ 6];
++      MACWork[ 5] = op->MACAddress[ 7];
++      MACWork[ 6] = op->MACAddress[ 9];
++      MACWork[ 7] = op->MACAddress[10];
++      MACWork[ 8] = op->MACAddress[12];
++      MACWork[ 9] = op->MACAddress[13];
++      MACWork[10] = op->MACAddress[15];
++      MACWork[11] = op->MACAddress[16];
++      MACWork[12] = '\0';
++      *var_len = 6;
++      return ( UCHAR * ) htob ( MACWork );
++        
++    case DOT11RTSTHRESHOLD:
++//    *write_method = write_dot11RTSThreshold;
++      return ( UCHAR * ) &op->RTSThreshold;
++
++    case DOT11SHORTRETRYLIMIT:
++//    *write_method = write_dot11ShortRetryLimit;
++      return ( UCHAR * ) &op->shortRetryLimit;
++
++    case DOT11LONGRETRYLIMIT:
++//    *write_method = write_dot11LongRetryLimit;
++      return ( UCHAR * ) &op->longRetryLimit;
++
++    case DOT11FRAGMENTATIONTHRESHOLD:
++//    *write_method = write_dot11FragmentationThreshold;
++      return ( UCHAR * ) &op->fragmentationThreshold;
++
++    case DOT11MAXTRANSMITMSDULIFETIME:
++//    *write_method = write_dot11MaxTransmitMSDULifetime;
++      return ( UCHAR * ) &op->maxTransmitMSDULifetime;
++
++    case DOT11MAXRECEIVELIFETIME:
++//    *write_method = write_dot11MaxReceiveLifetime;
++      return ( UCHAR * ) &op->maxReceiveLifetime;
++
++    case DOT11MANUFACTURERID:
++      *var_len = strlen ( op->manufacturerID );
++      return ( UCHAR * ) op->manufacturerID;
++
++    case DOT11PRODUCTID:
++      *var_len = strlen ( op->productID );
++      return ( UCHAR * ) op->productID;
++        
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*   var_dot11CountersTable() -                                              *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11CountersTable(struct variable *vp,
++          oid     *name,
++          size_t  *length,
++          int     exact,
++          size_t  *var_len,
++          WriteMethod **write_method)
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &coList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    co = ( struct coTbl_data * ) np->data;
++    rName[vp->namelen] = co->ifIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11TRANSMITTEDFRAGMENTCOUNT:
++          if ( co->haveTransmittedFragmentCount    ) found = TRUE; break;
++        case DOT11MULTICASTTRANSMITTEDFRAMECOUNT:
++          if ( co->haveTransmittedFrameCount       ) found = TRUE; break;
++        case DOT11FAILEDCOUNT:
++          if ( co->haveFailedCount                 ) found = TRUE; break;
++        case DOT11RETRYCOUNT:
++          if ( co->haveRetryCount                  ) found = TRUE; break;
++        case DOT11MULTIPLERETRYCOUNT:
++          if ( co->haveMultipleRetryCount          ) found = TRUE; break;
++        case DOT11FRAMEDUPLICATECOUNT:
++          if ( co->haveFrameDuplicateCount         ) found = TRUE; break;
++        case DOT11RTSSUCCESSCOUNT:
++          if ( co->haveRTSSuccessCount             ) found = TRUE; break;
++        case DOT11RTSFAILURECOUNT:
++          if ( co->haveRTSFailureCount             ) found = TRUE; break;
++        case DOT11ACKFAILURECOUNT:
++          if ( co->haveACKFailureCount             ) found = TRUE; break;
++        case DOT11RECEIVEDFRAGMENTCOUNT:
++          if ( co->haveReceivedFragmentCount       ) found = TRUE; break;
++        case DOT11MULTICASTRECEIVEDFRAMECOUNT:
++          if ( co->haveMulticastReceivedFrameCount ) found = TRUE; break;
++        case DOT11FCSERRORCOUNT:
++          if ( co->haveFCSErrorCount               ) found = TRUE; break;
++        case DOT11TRANSMITTEDFRAMECOUNT:
++          if ( co->haveTransmittedFrameCount       ) found = TRUE; break;
++        case DOT11WEPUNDECRYPTABLECOUNT:
++          if ( co->haveWEPUndecryptableCount       ) found = TRUE; break;
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 1 ) * sizeof ( oid ));
++  *length = vp->namelen + 1;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11TRANSMITTEDFRAGMENTCOUNT:       return ( UCHAR * ) &co->transmittedFragmentCount;
++    case DOT11MULTICASTTRANSMITTEDFRAMECOUNT: return ( UCHAR * ) &co->transmittedFrameCount;
++    case DOT11FAILEDCOUNT:                    return ( UCHAR * ) &co->failedCount;
++    case DOT11RETRYCOUNT:                     return ( UCHAR * ) &co->retryCount;
++    case DOT11MULTIPLERETRYCOUNT:             return ( UCHAR * ) &co->multipleRetryCount;
++    case DOT11FRAMEDUPLICATECOUNT:            return ( UCHAR * ) &co->frameDuplicateCount;
++    case DOT11RTSSUCCESSCOUNT:                return ( UCHAR * ) &co->RTSSuccessCount;
++    case DOT11RTSFAILURECOUNT:                return ( UCHAR * ) &co->RTSFailureCount;
++    case DOT11ACKFAILURECOUNT:                return ( UCHAR * ) &co->ACKFailureCount;
++    case DOT11RECEIVEDFRAGMENTCOUNT:          return ( UCHAR * ) &co->receivedFragmentCount;
++    case DOT11MULTICASTRECEIVEDFRAMECOUNT:    return ( UCHAR * ) &co->multicastReceivedFrameCount;
++    case DOT11FCSERRORCOUNT:                  return ( UCHAR * ) &co->FCSErrorCount;
++    case DOT11TRANSMITTEDFRAMECOUNT:          return ( UCHAR * ) &co->transmittedFrameCount;
++    case DOT11WEPUNDECRYPTABLECOUNT:          return ( UCHAR * ) &co->WEPUndecryptableCount;
++        
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*   var_dot11GroupAddressesTable() -                                        *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11GroupAddressesTable(struct variable *vp,
++          oid     *name,
++          size_t  *length,
++          int     exact,
++          size_t  *var_len,
++          WriteMethod **write_method)
++{
++  static char MACWork[17];
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &gaList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    ga = ( struct gaTbl_data * ) np->data;
++    rName[vp->namelen + 0] = ga->ifIndex;
++    rName[vp->namelen + 1] = ga->groupAddressesIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11ADDRESS:
++          if ( ga->haveAddress              ) found = TRUE; break;
++        case DOT11GROUPADDRESSESSTATUS:
++          if ( ga->haveGroupAddressesStatus ) found = TRUE; break;
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 2 ) * sizeof ( oid ));
++  *length = vp->namelen + 2;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11ADDRESS:
++//    *write_method = write_dot11Address;
++      MACWork[ 0] = ga->address[ 0];
++      MACWork[ 1] = ga->address[ 1];
++      MACWork[ 2] = ga->address[ 3];
++      MACWork[ 3] = ga->address[ 4];
++      MACWork[ 4] = ga->address[ 6];
++      MACWork[ 5] = ga->address[ 7];
++      MACWork[ 6] = ga->address[ 9];
++      MACWork[ 7] = ga->address[10];
++      MACWork[ 8] = ga->address[12];
++      MACWork[ 9] = ga->address[13];
++      MACWork[10] = ga->address[15];
++      MACWork[11] = ga->address[16];
++      MACWork[12] = '\0';
++      *var_len = 6;
++      return ( UCHAR * ) htob ( MACWork );
++
++    case DOT11GROUPADDRESSESSTATUS:
++//    *write_method = write_dot11GroupAddressesStatus;
++      return ( UCHAR * ) &ga->groupAddressesStatus;
++
++    default:
++      ERROR_MSG ( "" );
++  }
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*   var_dot11ResourceInfoTable() -                                          *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11ResourceInfoTable ( struct variable *vp,
++                              oid     *name,
++                              size_t  *length,
++                              int     exact,
++                              size_t  *var_len,
++                              WriteMethod **write_method )
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &riList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    ri = ( struct riTbl_data * ) np->data;
++    rName[vp->namelen] = ri->ifIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11MANUFACTUREROUI:
++          if ( ri->haveManufacturerOUI            ) found = TRUE; break;
++        case DOT11MANUFACTURERNAME:
++          if ( ri->haveManufacturerName           ) found = TRUE; break;
++        case DOT11MANUFACTURERPRODUCTNAME:
++          if ( ri->haveManufacturerProductName    ) found = TRUE; break;
++        case DOT11MANUFACTURERPRODUCTVERSION:
++          if ( ri->haveManufacturerProductVersion ) found = TRUE; break;
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 1 ) * sizeof ( oid ));
++  *length = vp->namelen + 1;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11MANUFACTUREROUI:
++      *var_len = strlen ( ri->manufacturerOUI );
++      return ( UCHAR * ) ri->manufacturerOUI;
++        
++    case DOT11MANUFACTURERNAME:
++      *var_len = strlen ( ri->manufacturerName );
++      return ( UCHAR * ) ri->manufacturerName;
++        
++    case DOT11MANUFACTURERPRODUCTNAME:
++      *var_len = strlen ( ri->manufacturerProductName );
++      return ( UCHAR * ) ri->manufacturerProductName;
++        
++    case DOT11MANUFACTURERPRODUCTVERSION:
++      *var_len = strlen ( ri->manufacturerProductVersion );
++      return ( UCHAR * ) ri->manufacturerProductVersion;
++        
++    default: 
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*   var_dot11PhyOperationTable() -                                          *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11PhyOperationTable ( struct variable *vp,
++                              oid     *name,
++                              size_t  *length,
++                              int     exact,
++                              size_t  *var_len,
++                              WriteMethod **write_method )
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &poList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    po = ( struct poTbl_data * ) np->data;
++    rName[vp->namelen] = po->ifIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11PHYTYPE:
++          if ( po->havePHYType          ) found = TRUE; break;
++        case DOT11CURRENTREGDOMAIN:
++          if ( po->haveCurrentRegDomain ) found = TRUE; break;
++        case DOT11TEMPTYPE:
++          if ( po->haveTempType         ) found = TRUE; break;
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 1 ) * sizeof ( oid ));
++  *length = vp->namelen + 1;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11PHYTYPE:
++      return ( UCHAR * ) &po->PHYType;
++        
++    case DOT11CURRENTREGDOMAIN:
++//    *write_method = write_dot11CurrentRegDomain;
++      return ( UCHAR * ) &po->currentRegDomain;
++
++    case DOT11TEMPTYPE:
++      return ( UCHAR * ) &po->tempType;
++        
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*   var_dot11PhyAntennaTable() -                                            *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11PhyAntennaTable ( struct variable *vp,
++                            oid     *name,
++                            size_t  *length,
++                            int     exact,
++                            size_t  *var_len,
++                            WriteMethod **write_method )
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &paList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    pa = ( struct paTbl_data * ) np->data;
++    rName[vp->namelen] = pa->ifIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11CURRENTTXANTENNA:
++          if ( pa->haveCurrentTxAntenna ) found = TRUE; break;
++        case DOT11DIVERSITYSUPPORT:
++          if ( pa->haveDiversitySupport ) found = TRUE; break;
++        case DOT11CURRENTRXANTENNA:
++          if ( pa->haveCurrentRxAntenna ) found = TRUE; break;
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 1 ) * sizeof ( oid ));
++  *length = vp->namelen + 1;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11CURRENTTXANTENNA:
++//    *write_method = write_dot11CurrentTxAntenna;
++      return ( UCHAR * ) &pa->currentTxAntenna;
++
++    case DOT11DIVERSITYSUPPORT:
++      return ( UCHAR * ) &pa->diversitySupport;
++        
++    case DOT11CURRENTRXANTENNA:
++//    *write_method = write_dot11CurrentRxAntenna;
++      return ( UCHAR * ) &pa->currentRxAntenna;
++
++    default:
++      ERROR_MSG ( "" );
++  }
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*   var_dot11PhyTxPowerTable() -                                            *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11PhyTxPowerTable ( struct variable *vp,
++                            oid     *name,
++                            size_t  *length,
++                            int     exact,
++                            size_t  *var_len,
++                            WriteMethod **write_method )
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &ptList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    pt = ( struct ptTbl_data * ) np->data;
++    rName[vp->namelen] = pt->ifIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11NUMBERSUPPORTEDPOWERLEVELS:
++          if ( pt->haveNumberSupportedPowerLevels ) found = TRUE; break;
++        case DOT11TXPOWERLEVEL1:
++          if ( pt->haveTxPowerLevel1   ) found = TRUE; break;
++        case DOT11TXPOWERLEVEL2:
++          if ( pt->haveTxPowerLevel2   ) found = TRUE; break;
++        case DOT11TXPOWERLEVEL3:
++          if ( pt->haveTxPowerLevel3   ) found = TRUE; break;
++        case DOT11TXPOWERLEVEL4:
++          if ( pt->haveTxPowerLevel4   ) found = TRUE; break;
++        case DOT11TXPOWERLEVEL5:
++          if ( pt->haveTxPowerLevel5   ) found = TRUE; break;
++        case DOT11TXPOWERLEVEL6:
++          if ( pt->haveTxPowerLevel6   ) found = TRUE; break;
++        case DOT11TXPOWERLEVEL7:
++          if ( pt->haveTxPowerLevel7   ) found = TRUE; break;
++        case DOT11TXPOWERLEVEL8:
++          if ( pt->haveTxPowerLevel8   ) found = TRUE; break;
++        case DOT11CURRENTTXPOWERLEVEL:
++          if ( pt->currentTxPowerLevel ) found = TRUE; break;
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 1 ) * sizeof ( oid ));
++  *length = vp->namelen + 1;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11NUMBERSUPPORTEDPOWERLEVELS: 
++      return ( UCHAR * ) &pt->numberSupportedPowerLevels;
++
++    case DOT11TXPOWERLEVEL1: return ( UCHAR * ) &pt->TxPowerLevel1;
++    case DOT11TXPOWERLEVEL2: return ( UCHAR * ) &pt->TxPowerLevel2;
++    case DOT11TXPOWERLEVEL3: return ( UCHAR * ) &pt->TxPowerLevel3;
++    case DOT11TXPOWERLEVEL4: return ( UCHAR * ) &pt->TxPowerLevel4;
++    case DOT11TXPOWERLEVEL5: return ( UCHAR * ) &pt->TxPowerLevel5;
++    case DOT11TXPOWERLEVEL6: return ( UCHAR * ) &pt->TxPowerLevel6;
++    case DOT11TXPOWERLEVEL7: return ( UCHAR * ) &pt->TxPowerLevel7;
++    case DOT11TXPOWERLEVEL8: return ( UCHAR * ) &pt->TxPowerLevel8;
++        
++    case DOT11CURRENTTXPOWERLEVEL:
++//    *write_method = write_dot11CurrentTxPowerLevel;
++      return ( UCHAR * ) &pt->currentTxPowerLevel;
++
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*     var_dot11PhyFHSSTable() -                                             *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11PhyFHSSTable ( struct variable *vp,
++                        oid     *name,
++                        size_t  *length,
++                        int     exact,
++                        size_t  *var_len,
++                        WriteMethod **write_method )
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &pfList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    pf = ( struct pfTbl_data * ) np->data;
++    rName[vp->namelen] = pf->ifIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11HOPTIME:
++          if ( pf->haveHopTime              ) found = TRUE; break;
++        case DOT11CURRENTCHANNELNUMBER:
++          if ( pf->haveCurrentChannelNumber ) found = TRUE; break;
++        case DOT11MAXDWELLTIME:
++          if ( pf->haveMaxDwellTime         ) found = TRUE; break;
++        case DOT11CURRENTDWELLTIME:
++          if ( pf->haveCurrentDwellTime     ) found = TRUE; break;
++        case DOT11CURRENTSET:
++          if ( pf->haveCurrentSet           ) found = TRUE; break;
++        case DOT11CURRENTPATTERN:
++          if ( pf->haveCurrentPattern       ) found = TRUE; break;
++        case DOT11CURRENTINDEX:
++          if ( pf->haveCurrentIndex         ) found = TRUE; break;
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 1 ) * sizeof ( oid ));
++  *length = vp->namelen + 1;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11HOPTIME:
++      return ( UCHAR * ) &pf->hopTime;
++        
++    case DOT11CURRENTCHANNELNUMBER:
++//    *write_method = write_dot11CurrentChannelNumber;
++      return ( UCHAR * ) &pf->currentChannelNumber;
++
++    case DOT11MAXDWELLTIME:
++      return ( UCHAR * ) &pf->maxDwellTime;
++        
++    case DOT11CURRENTDWELLTIME:
++//    *write_method = write_dot11CurrentDwellTime;
++      return ( UCHAR * ) &pf->currentDwellTime;
++
++    case DOT11CURRENTSET:
++//    *write_method = write_dot11CurrentSet;
++      return ( UCHAR * ) &pf->currentSet;
++
++    case DOT11CURRENTPATTERN:
++//    *write_method = write_dot11CurrentPattern;
++      return ( UCHAR * ) &pf->currentPattern;
++
++    case DOT11CURRENTINDEX:
++//    *write_method = write_dot11CurrentIndex;
++      return ( UCHAR * ) &pf->currentIndex;
++
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*     var_dot11PhyDSSSTable() -                                             *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11PhyDSSSTable ( struct variable *vp,
++                        oid     *name,
++                        size_t  *length,
++                        int     exact,
++                        size_t  *var_len,
++                        WriteMethod **write_method )
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &pdList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    pd = ( struct pdTbl_data * ) np->data;
++    rName[vp->namelen] = pd->ifIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11CURRENTCHANNEL:
++          if ( pd->haveCurrentChannel   ) found = TRUE; break;
++        case DOT11CCAMODESUPPORTED:
++          if ( pd->haveCCAModeSupported ) found = TRUE; break;
++        case DOT11CURRENTCCAMODE:
++          if ( pd->haveCurrentCCAMode   ) found = TRUE; break;
++        case DOT11EDTHRESHOLD:
++          if ( pd->haveEDThreshold      ) found = TRUE; break;
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 1 ) * sizeof ( oid ));
++  *length = vp->namelen + 1;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11CURRENTCHANNEL:
++//    *write_method = write_dot11CurrentChannel;
++      return ( UCHAR * ) &pd->currentChannel;
++
++    case DOT11CCAMODESUPPORTED:
++      return ( UCHAR * ) &pd->CCAModeSupported;
++        
++    case DOT11CURRENTCCAMODE:
++//    *write_method = write_dot11CurrentCCAMode;
++      return ( UCHAR * ) &pd->currentCCAMode;
++
++    case DOT11EDTHRESHOLD:
++//    *write_method = write_dot11EDThreshold;
++      return ( UCHAR * ) &pd->EDThreshold;
++
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*     var_dot11PhyIRTable() -                                             *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11PhyIRTable ( struct variable *vp,
++                      oid     *name,
++                      size_t  *length,
++                      int     exact,
++                      size_t  *var_len,
++                      WriteMethod **write_method)
++{
++
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &piList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    pi = ( struct piTbl_data * ) np->data;
++    rName[vp->namelen] = pi->ifIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 1, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11CCAWATCHDOGTIMERMAX:
++          if ( pi->CCAWatchdogTimerMax ) found = TRUE; break;
++        case DOT11CCAWATCHDOGCOUNTMAX:
++          if ( pi->CCAWatchdogCountMax ) found = TRUE; break;
++        case DOT11CCAWATCHDOGTIMERMIN:
++          if ( pi->CCAWatchdogTimerMin ) found = TRUE; break;
++        case DOT11CCAWATCHDOGCOUNTMIN:
++          if ( pi->CCAWatchdogCountMin ) found = TRUE; break;
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 1 ) * sizeof ( oid ));
++  *length = vp->namelen + 1;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11CCAWATCHDOGTIMERMAX:
++//    *write_method = write_dot11CCAWatchdogTimerMax;
++      return ( UCHAR * ) &pi->CCAWatchdogTimerMax;
++
++    case DOT11CCAWATCHDOGCOUNTMAX:
++//   *write_method = write_dot11CCAWatchdogCountMax;
++      return ( UCHAR * ) &pi->CCAWatchdogCountMax;
++
++    case DOT11CCAWATCHDOGTIMERMIN:
++//    *write_method = write_dot11CCAWatchdogTimerMin;
++      return ( UCHAR * ) &pi->CCAWatchdogTimerMin;
++
++    case DOT11CCAWATCHDOGCOUNTMIN:
++//    *write_method = write_dot11CCAWatchdogCountMin;
++      return ( UCHAR * ) &pi->CCAWatchdogCountMin;
++
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*     var_dot11RegDomainsSupportedTable() -                                 *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11RegDomainsSupportedTable ( struct variable *vp,
++                                    oid     *name,
++                                    size_t  *length,
++                                    int     exact,
++                                    size_t  *var_len,
++                                    WriteMethod **write_method)
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &rdList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    rd = ( struct rdTbl_data * ) np->data;
++    rName[vp->namelen + 0] = rd->ifIndex;
++    rName[vp->namelen + 1] = rd->regDomainsSupportIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11REGDOMAINSSUPPORTVALUE:
++          if ( rd->haveRegDomainsSupportValue ) found = TRUE; break;
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 2 ) * sizeof ( oid ));
++  *length = vp->namelen + 2;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11REGDOMAINSSUPPORTVALUE:
++      return ( UCHAR * ) &rd->regDomainsSupportValue;
++        
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*     var_dot11AntennasListTable() -                                        *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11AntennasListTable(struct variable *vp,
++          oid     *name,
++          size_t  *length,
++          int     exact,
++          size_t  *var_len,
++          WriteMethod **write_method)
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &alList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    al = ( struct alTbl_data * ) np->data;
++    rName[vp->namelen + 0] = al->ifIndex;
++    rName[vp->namelen + 1] = al->antennaListIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11SUPPORTEDTXANTENNA:
++          if ( al->haveSupportedTxAntenna   ) found = TRUE; break;
++        case DOT11SUPPORTEDRXANTENNA:
++          if ( al->haveSupportedRxAntenna   ) found = TRUE; break;
++        case DOT11DIVERSITYSELECTIONRX:
++          if ( al->haveDiversitySelectionRx ) found = TRUE; break;
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 2 ) * sizeof ( oid ));
++  *length = vp->namelen + 2;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11SUPPORTEDTXANTENNA:
++//    *write_method = write_dot11SupportedTxAntenna;
++      return ( UCHAR * ) &al->supportedTxAntenna;
++
++    case DOT11SUPPORTEDRXANTENNA:
++//    *write_method = write_dot11SupportedRxAntenna;
++      return ( UCHAR * ) &al->supportedRxAntenna;
++
++    case DOT11DIVERSITYSELECTIONRX:
++//    *write_method = write_dot11DiversitySelectionRx;
++      return ( UCHAR * ) &al->diversitySelectionRx;
++
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*     var_dot11SupportedDataRatesTxTable() -                                *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11SupportedDataRatesTxTable ( struct variable *vp,
++                                      oid     *name,
++                                      size_t  *length,
++                                      int     exact,
++                                      size_t  *var_len,
++                                      WriteMethod **write_method )
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &rtList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    rt = ( struct rtTbl_data * ) np->data;
++    rName[vp->namelen + 0] = rt->ifIndex;
++    rName[vp->namelen + 1] = rt->supportedDataRatesTxIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++         case DOT11SUPPORTEDDATARATESTXVALUE:
++          if ( rt->haveSupportedDataRatesTxValue ) found = TRUE; break;
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 2 ) * sizeof ( oid ));
++  *length = vp->namelen + 2;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11SUPPORTEDDATARATESTXVALUE:
++      return ( UCHAR * ) &rt->supportedDataRatesTxValue;
++        
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++*     var_dot11SupportedDataRatesRxTable() -                                *
++*                                                                           *
++****************************************************************************/
++unsigned char *
++var_dot11SupportedDataRatesRxTable ( struct variable *vp,
++                                      oid     *name,
++                                      size_t  *length,
++                                      int     exact,
++                                      size_t  *var_len,
++                                      WriteMethod **write_method )
++{
++  int found = FALSE;
++  oid rName [ MAX_OID_LEN ];                            // OID to be returned
++
++  loadTables();
++  memcpy (( char * ) rName, ( char * ) vp->name, ( int ) vp->namelen * sizeof ( oid ));
++  for ( np = LIST_FIRST ( &rrList ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    rr = ( struct rrTbl_data * ) np->data;
++    rName[vp->namelen + 0] = rr->ifIndex;
++    rName[vp->namelen + 1] = rr->supportedDataRatesRxIndex;
++    if ((  exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) == 0 )) ||
++        ( !exact && ( snmp_oid_compare ( rName, vp->namelen + 2, name, *length ) >  0 ))) {
++      switch ( vp->magic ) {
++        case DOT11SUPPORTEDDATARATESRXVALUE:
++          if ( rr->haveSupportedDataRatesRxValue ) found = TRUE; break;
++      }
++    }
++    if ( found )
++      break;
++  }
++
++  if ( !found ) 
++    return NULL;
++
++  memcpy (( char * ) name, ( char * ) rName, ( vp->namelen + 2 ) * sizeof ( oid ));
++  *length = vp->namelen + 2;
++  *var_len = sizeof ( long );
++  *write_method = NULL;
++
++  switch ( vp->magic ) {
++
++    case DOT11SUPPORTEDDATARATESRXVALUE:
++      return ( UCHAR * ) &rr->supportedDataRatesRxValue;
++        
++    default:
++      ERROR_MSG ( "" );
++  }
++
++  return NULL;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11StationID(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static unsigned char string[SPRINT_MAX_LEN];
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_OCTET_STR ) {
++        fprintf ( stderr, "write to dot11StationID not ASN_OCTET_STR\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( string )) {
++        fprintf ( stderr,"write to dot11StationID: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11MediumOccupancyLimit(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11MediumOccupancyLimit not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr,"write to dot11MediumOccupancyLimit: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CFPPeriod(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CFPPeriod not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11CFPPeriod: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CFPMaxDuration(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CFPMaxDuration not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11CFPMaxDuration: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11AuthenticationResponseTimeOut(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11AuthenticationResponseTimeOut not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11AuthenticationResponseTimeOut: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11PowerManagementMode(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11PowerManagementMode not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )) {
++        fprintf ( stderr, "write to dot11PowerManagementMode: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11DesiredSSID(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static unsigned char string[SPRINT_MAX_LEN];
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_OCTET_STR ) {
++        fprintf ( stderr, "write to dot11DesiredSSID not ASN_OCTET_STR\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( string )){
++        fprintf ( stderr, "write to dot11DesiredSSID: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11DesiredBSSType(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11DesiredBSSType not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11DesiredBSSType: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11OperationalRateSet(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static unsigned char string[SPRINT_MAX_LEN];
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_OCTET_STR ) {
++        fprintf ( stderr, "write to dot11OperationalRateSet not ASN_OCTET_STR\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( string )){
++        fprintf ( stderr, "write to dot11OperationalRateSet: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11BeaconPeriod(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11BeaconPeriod not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr,"write to dot11BeaconPeriod: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11DTIMPeriod(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11DTIMPeriod not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr,"write to dot11DTIMPeriod: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11AssociationResponseTimeOut(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11AssociationResponseTimeOut not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )) {
++        fprintf ( stderr,"write to dot11AssociationResponseTimeOut: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11AuthenticationAlgorithmsEnable(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11AuthenticationAlgorithmsEnable not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr,"write to dot11AuthenticationAlgorithmsEnable: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11WEPDefaultKeyValue(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static unsigned char string[SPRINT_MAX_LEN];
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_OCTET_STR ) {
++        fprintf ( stderr, "write to dot11WEPDefaultKeyValue not ASN_OCTET_STR\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( string )){
++        fprintf ( stderr,"write to dot11WEPDefaultKeyValue: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11WEPKeyMappingAddress(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static unsigned char string[SPRINT_MAX_LEN];
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_OCTET_STR ) {
++        fprintf ( stderr, "write to dot11WEPKeyMappingAddress not ASN_OCTET_STR\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( string )) {
++        fprintf ( stderr,"write to dot11WEPKeyMappingAddress: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11WEPKeyMappingWEPOn(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11WEPKeyMappingWEPOn not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11WEPKeyMappingWEPOn: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11WEPKeyMappingValue(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static unsigned char string[SPRINT_MAX_LEN];
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_OCTET_STR ) {
++        fprintf ( stderr, "write to dot11WEPKeyMappingValue not ASN_OCTET_STR\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( string )) {
++        fprintf ( stderr, "write to dot11WEPKeyMappingValue: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11WEPKeyMappingStatus(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11WEPKeyMappingStatus not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11WEPKeyMappingStatus: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11PrivacyInvoked(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11PrivacyInvoked not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11PrivacyInvoked: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11WEPDefaultKeyID(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11WEPDefaultKeyID not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11WEPDefaultKeyID: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11WEPKeyMappingLength(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11WEPKeyMappingLength not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11WEPKeyMappingLength: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11ExcludeUnencrypted(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11ExcludeUnencrypted not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr,"write to dot11ExcludeUnencrypted: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11RTSThreshold(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ){
++        fprintf ( stderr, "write to dot11RTSThreshold not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11RTSThreshold: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11ShortRetryLimit(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11ShortRetryLimit not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11ShortRetryLimit: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11LongRetryLimit(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11LongRetryLimit not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr,"write to dot11LongRetryLimit: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11FragmentationThreshold(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11FragmentationThreshold not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr,"write to dot11FragmentationThreshold: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11MaxTransmitMSDULifetime(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11MaxTransmitMSDULifetime not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11MaxTransmitMSDULifetime: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11MaxReceiveLifetime(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11MaxReceiveLifetime not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11MaxReceiveLifetime: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11Address(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static unsigned char string[SPRINT_MAX_LEN];
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_OCTET_STR ) {
++        fprintf ( stderr, "write to dot11Address not ASN_OCTET_STR\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( string )){
++        fprintf ( stderr, "write to dot11Address: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11GroupAddressesStatus(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11GroupAddressesStatus not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr,"write to dot11GroupAddressesStatus: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CurrentRegDomain(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CurrentRegDomain not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11CurrentRegDomain: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CurrentTxAntenna(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CurrentTxAntenna not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11CurrentTxAntenna: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CurrentRxAntenna(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CurrentRxAntenna not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr,"write to dot11CurrentRxAntenna: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CurrentTxPowerLevel(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CurrentTxPowerLevel not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11CurrentTxPowerLevel: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CurrentChannelNumber(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CurrentChannelNumber not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr,"write to dot11CurrentChannelNumber: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CurrentDwellTime(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CurrentDwellTime not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11CurrentDwellTime: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CurrentSet(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CurrentSet not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11CurrentSet: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CurrentPattern(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CurrentPattern not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11CurrentPattern: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CurrentIndex(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CurrentIndex not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11CurrentIndex: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CurrentChannel(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CurrentChannel not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11CurrentChannel: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CurrentCCAMode(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CurrentCCAMode not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr,"write to dot11CurrentCCAMode: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11EDThreshold(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11EDThreshold not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11EDThreshold: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CCAWatchdogTimerMax(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CCAWatchdogTimerMax not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11CCAWatchdogTimerMax: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CCAWatchdogCountMax(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CCAWatchdogCountMax not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11CCAWatchdogCountMax: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CCAWatchdogTimerMin(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CCAWatchdogTimerMin not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11CCAWatchdogTimerMin: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11CCAWatchdogCountMin(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11CCAWatchdogCountMin not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11CCAWatchdogCountMin: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11SupportedTxAntenna(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11SupportedTxAntenna not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11SupportedTxAntenna: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11SupportedRxAntenna(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11SupportedRxAntenna not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr,"write to dot11SupportedRxAntenna: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++int
++write_dot11DiversitySelectionRx(int      action,
++            u_char   *var_val,
++            u_char   var_val_type,
++            size_t   var_val_len,
++            u_char   *statP,
++            oid      *name,
++            size_t   name_len)
++{
++  static long *long_ret;
++  int size;
++
++  switch ( action ) {
++
++    case RESERVE1:
++      if ( var_val_type != ASN_INTEGER ) {
++        fprintf ( stderr, "write to dot11DiversitySelectionRx not ASN_INTEGER\n" );
++        return SNMP_ERR_WRONGTYPE;
++      }
++      if ( var_val_len > sizeof ( long_ret )){
++        fprintf ( stderr, "write to dot11DiversitySelectionRx: bad length\n" );
++        return SNMP_ERR_WRONGLENGTH;
++      }
++      break;
++
++    case RESERVE2:
++    case FREE:
++    case ACTION:
++    case UNDO:
++      break;
++
++    case COMMIT:
++      break;
++  }
++
++  return SNMP_ERR_NOERROR;
++}
++
++/****************************************************************************
++*                                                                           *
++*                      loadTables() - Load the Tables                       *
++*                                                                           *
++****************************************************************************/
++static void loadTables()
++{
++  int skfd;                               // generic raw socket desc
++  struct iwreq wrq;                       // ioctl request structure
++  struct ifreq ifr;
++  struct timeval et;                      // elapsed time
++  struct wireless_info info;              // workarea for wireless ioctl information
++  FILE *fp;
++  char  bfr[1024], ifName[1024];
++  char *s, *t;
++
++  gettimeofday ( &et, ( struct timezone * ) 0 );  // get time-of-day
++  if ( et.tv_sec < lastLoad + MINLOADFREQ )       // only reload so often
++    return;
++  lastLoad = et.tv_sec;
++
++  skfd = openSocket();                            // open socket
++  if ( skfd < 0 ) {
++    syslog ( LOG_ERR, "SNMP ieee802dot11.loadTables() - %s\n", "socket open failure" );
++    return;
++  }
++
++  flushLists();
++
++  // find interfaces in /proc/net/dev and find the wireless interfaces
++  fp = fopen ( PROC_NET_DEV, "r" );
++  if ( fp ) {
++    while ( fgets ( bfr, sizeof ( bfr ), fp )) {
++      if ( strstr ( bfr, ":" )) {
++        s = bfr; t = ifName;
++        while ( isspace ( *s ))                     // discard white space
++          *s++;
++        while ( *s != ':' )                         // get interface name
++          *t++ = *s++;
++        *t = '\0';
++
++        // verify as a wireless device
++        memset (( char * ) &info, 0, sizeof ( struct wireless_info ));
++        strncpy ( wrq.ifr_name, ifName, IFNAMSIZ );
++        if ( ioctl ( skfd, SIOCGIWNAME, &wrq ) >= 0 ) {
++          printf ( "%s ifName: %s\n", "loadTables() -", ifName );
++          initStructs();
++          loadWiExt( skfd, ifName, &info );
++          displayWiExt ( info );
++          load80211Structs ( skfd, ifName, &info );
++        }
++      }
++    }
++    fclose ( fp );
++  }
++
++  close ( skfd );
++}
++
++/****************************************************************************
++*                                                                           *
++*              load80211Structs() - load the 802.11 structures              *
++*                                                                           *
++****************************************************************************/
++static void 
++load80211Structs ( int skfd, char *ifName, struct wireless_info *wi )
++{
++  int rc, ifIndex = 0;
++  struct ifreq ifr;
++  char  MACAddress [ MACADDR_LEN + 1 ];
++
++  strcpy ( ifr.ifr_name, ifName );
++  rc = ioctl ( skfd, SIOCGIFHWADDR, &ifr );
++  if ( rc >= 0 ) {
++
++    sprintf ( MACAddress, "%02X:%02X:%02X:%02X:%02X:%02X\0", 
++                 ( UCHAR ) ifr.ifr_hwaddr.sa_data[0], ( UCHAR ) ifr.ifr_hwaddr.sa_data[1], 
++                 ( UCHAR ) ifr.ifr_hwaddr.sa_data[2], ( UCHAR ) ifr.ifr_hwaddr.sa_data[3], 
++                 ( UCHAR ) ifr.ifr_hwaddr.sa_data[4], ( UCHAR ) ifr.ifr_hwaddr.sa_data[5] );
++
++    nSc.haveStationID = TRUE;
++    strcpy  ( nSc.stationID, MACAddress );
++    nOp.haveMACAddress = TRUE;
++    strcpy  ( nOp.MACAddress, MACAddress );
++    nRi.haveManufacturerOUI = TRUE;
++    strncpy ( nRi.manufacturerOUI, MACAddress, MAN_OUI_LEN ); 
++
++    ifIndex = if_nametoindex ( ifName );
++    if ( !ifIndex ) {
++      syslog ( LOG_ERR, "SNMP %s - %s %s\n", 
++        "ieee802dot11.load80211Structs()", ifName, "has no ifIndex" );
++      return;
++    }
++
++    loadWiExtTo80211Structs ( ifIndex, ifName, wi );
++
++    if ( hasChanged (( char * ) &nSc, sizeof ( nSc ))) {
++      nSc.ifIndex = ifIndex;
++      sprintf ( nSc.UID, "%04d\0", nSc.ifIndex );
++      strcpy ( nSc.ifName, ifName );
++      addList (( char * ) &scList, ( char * ) &nSc, sizeof ( nSc ));
++    }
++
++    if ( hasChanged (( char * ) &nPr, sizeof ( nPr ))) {
++      nPr.ifIndex = ifIndex;
++      sprintf ( nPr.UID, "%04d\0", nPr.ifIndex );
++      strcpy ( nPr.ifName, ifName );
++      addList (( char * ) &prList, ( char * ) &nPr, sizeof ( nPr ));
++    }
++
++    if ( hasChanged (( char * ) &nOp, sizeof ( nOp ))) {
++      nOp.ifIndex = ifIndex;
++      sprintf ( nOp.UID, "%04d\0", nOp.ifIndex );
++      strcpy ( nOp.ifName, ifName );
++      addList (( char * ) &opList, ( char * ) &nOp, sizeof ( nOp ));
++    }
++
++    if ( hasChanged (( char * ) &nCo, sizeof ( nCo ))) {
++      nCo.ifIndex = ifIndex;
++      sprintf ( nCo.UID, "%04d\0", nCo.ifIndex );
++      strcpy ( nCo.ifName, ifName );
++      addList (( char * ) &coList, ( char * ) &nCo, sizeof ( nCo ));
++    }
++
++    if ( hasChanged (( char * ) &nRi, sizeof ( nRi ))) {
++      nRi.ifIndex = ifIndex;
++      sprintf ( nRi.UID, "%04d\0", nRi.ifIndex );
++      strcpy ( nRi.ifName, ifName );
++      addList (( char * ) &riList, ( char * ) &nRi, sizeof ( nRi ));
++    }
++
++    if ( hasChanged (( char * ) &nPo, sizeof ( nPo ))) {
++      nPo.ifIndex = ifIndex;
++      sprintf ( nPo.UID, "%04d\0", nPo.ifIndex );
++      strcpy ( nPo.ifName, ifName );
++      addList (( char * ) &poList, ( char * ) &nPo, sizeof ( nPo ));
++    }
++
++    if ( hasChanged (( char * ) &nPa, sizeof ( nPa ))) {
++      nPa.ifIndex = ifIndex;
++      sprintf ( nPa.UID, "%04d\0", nPa.ifIndex );
++      strcpy ( nPa.ifName, ifName );
++      addList (( char * ) &paList, ( char * ) &nPa, sizeof ( nPa ));
++    }
++
++    if ( hasChanged (( char * ) &nPt, sizeof ( nPt ))) {
++      nPt.ifIndex = ifIndex;
++      sprintf ( nPt.UID, "%04d\0", nPt.ifIndex );
++      strcpy ( nPt.ifName, ifName );
++      addList (( char * ) &ptList, ( char * ) &nPt, sizeof ( nPt ));
++    }
++
++    if ( hasChanged (( char * ) &nPf, sizeof ( nPf ))) {
++      nPf.ifIndex = ifIndex;
++      sprintf ( nPf.UID, "%04d\0", nPf.ifIndex );
++      strcpy ( nPf.ifName, ifName );
++      addList (( char * ) &pfList, ( char * ) &nPf, sizeof ( nPf ));
++    }
++
++    if ( hasChanged (( char * ) &nPd, sizeof ( nPd ))) {
++      nPd.ifIndex = ifIndex;
++      sprintf ( nPd.UID, "%04d\0", nPd.ifIndex );
++      strcpy ( nPd.ifName, ifName );
++      addList (( char * ) &pdList, ( char * ) &nPd, sizeof ( nPd ));
++    }
++
++    if ( hasChanged (( char * ) &nPi, sizeof ( nPi ))) {
++      nPi.ifIndex = ifIndex;
++      sprintf ( nPi.UID, "%04d\0", nPi.ifIndex );
++      strcpy ( nPi.ifName, ifName );
++      addList (( char * ) &piList, ( char * ) &nPi, sizeof ( nPi ));
++    }
++  }
++
++//printf ( "%s - ifIndex: %d ifName: %s UID: %s\n", 
++//         "load80211Structs() - HASCHANGED", ifIndex, ifName, nSc.UID );
++}
++
++/****************************************************************************
++*                                                                           *
++*                     initStructs() - initialize structures                 *
++*                                                                           *
++****************************************************************************/
++static void initStructs()
++{
++  int i;
++
++  // 802.11 MIB Stuctures
++  memset (( char * ) &nSc, 0, sizeof ( nSc ));  memset (( char * ) &nAa, 0, sizeof ( nAa ));
++  memset (( char * ) &nDf, 0, sizeof ( nDf ));  memset (( char * ) &nKm, 0, sizeof ( nKm ));
++  memset (( char * ) &nPr, 0, sizeof ( nPr ));  memset (( char * ) &nOp, 0, sizeof ( nOp ));
++  memset (( char * ) &nCo, 0, sizeof ( nCo ));  memset (( char * ) &nGa, 0, sizeof ( nGa ));
++  memset (( char * ) &nRi, 0, sizeof ( nRi ));  memset (( char * ) &nPo, 0, sizeof ( nPo ));
++  memset (( char * ) &nPa, 0, sizeof ( nPa ));  memset (( char * ) &nPt, 0, sizeof ( nPt ));
++  memset (( char * ) &nPf, 0, sizeof ( nPf ));  memset (( char * ) &nPd, 0, sizeof ( nPd ));
++  memset (( char * ) &nPi, 0, sizeof ( nPi ));  memset (( char * ) &nRd, 0, sizeof ( nRd ));
++  memset (( char * ) &nAl, 0, sizeof ( nAl ));  memset (( char * ) &nRt, 0, sizeof ( nRt ));
++  memset (( char * ) &nRr, 0, sizeof ( nRr ));
++
++  // Wireless Extensions
++  wepCurrentKey = 0;
++  haveWepCurrentKey = FALSE;
++  for ( i = 0; i < MAX_WEP_KEYS; i++ ) {
++    wep[i].len = 0;
++    wep[i].key[0] = '\0';
++    wep[i].haveKey = FALSE;
++  }
++}
++
++/****************************************************************************
++*                                                                           *
++*                Wireless Extensions Specific Functions                     *
++*                                                                           *
++****************************************************************************/
++/****************************************************************************
++*                                                                           *
++* loadWiExtTo80211Structs() - load wireless extensions to 802.11 structures *
++*                                                                           *
++****************************************************************************/
++static void 
++loadWiExtTo80211Structs ( int ifIndex, char *ifName, struct wireless_info *wi )
++{
++  int i, j = 0;
++
++  // dot11Smt Group
++  // dot11StationConfigTable
++  nSc.havePrivacyOptionImplemented = TRUE;
++  nSc.privacyOptionImplemented = 1;           // assume we support WEP
++
++  if ( wi->has_power ) {
++    nSc.havePowerManagementMode = TRUE;
++    nSc.powerManagementMode = 1;              // assume power is active
++    if ( !wi->power.disabled && 
++          wi->power.flags & IW_POWER_MIN )
++      nSc.powerManagementMode = 2;            // power save mode
++  }
++
++  if ( wi->has_essid && strlen ( wi->essid )) {
++    nSc.haveDesiredSSID = TRUE;
++    strcpy ( nSc.desiredSSID, wi->essid ); 
++  }
++
++  if ( wi->has_mode ) {
++    nSc.haveDesiredBSSType = TRUE;
++    if ( wi->mode == IW_MODE_ADHOC ) 
++      nSc.desiredBSSType = 2;         // independent
++    else if ( wi->has_ap_addr )
++      nSc.desiredBSSType = 1;         // infrastructure
++    else
++      nSc.desiredBSSType = 3;         // any
++  }
++
++  if ( wi->has_range ) {
++    for ( i = 0; i < wi->range.num_bitrates && j < 126; i++ ) {
++      nSc.haveOperationalRateSet = TRUE;
++      nSc.operationalRateSet[j++] = ( char ) ( wi->range.bitrate[i] / 500000L );
++    }
++  }
++
++  // dot11AuthenticationAlgorithmsTable
++  nAa.haveAuthenticationAlgorithm = TRUE;           // it's a rule to always have 
++  nAa.haveAuthenticationAlgorithmsEnable = TRUE;    //    'open' supported
++  nAa.ifIndex = ifIndex;
++  nAa.authenticationAlgorithmsIndex = 1;            // index number one
++  nAa.authenticationAlgorithm = 1;                  // 1 => open key
++  sprintf ( nAa.UID, "%04d%04d\0", nAa.ifIndex, nAa.authenticationAlgorithmsIndex );
++  nAa.authenticationAlgorithmsEnable = 1;           // enabled by default
++  if ( ( wi->has_key                        ) &&
++       ( wi->key_size  != 0                 ) &&
++      !( wi->key_flags & IW_ENCODE_DISABLED ))
++    nAa.authenticationAlgorithmsEnable = 2;
++  addList (( char * ) &aaList, ( char * ) &nAa, sizeof ( nAa ));
++
++  nAa.haveAuthenticationAlgorithm = TRUE;           // I'm gonna assume we always support WEP
++  nAa.haveAuthenticationAlgorithmsEnable = TRUE;
++  nAa.ifIndex = ifIndex;
++  nAa.authenticationAlgorithmsIndex = 2;            // index number 2
++  nAa.authenticationAlgorithm = 2;                  // 2 => shared key
++  sprintf ( nAa.UID, "%04d%04d\0", nAa.ifIndex, nAa.authenticationAlgorithmsIndex );
++  nAa.authenticationAlgorithmsEnable = 2;
++  if ( ( wi->has_key                        ) &&
++       ( wi->key_size  != 0                 ) &&
++      !( wi->key_flags & IW_ENCODE_DISABLED ))
++    nAa.authenticationAlgorithmsEnable = 1;         // disabled by default
++  addList (( char * ) &aaList, ( char * ) &nAa, sizeof ( nAa ));
++
++  //dot11WEPDefaultKeysTable
++  if ( wi->has_range ) {
++    for ( i = 0; i < MAX_WEP_KEYS; i++ ) {
++      nDf.haveWEPDefaultKeyValue = TRUE;
++      nDf.ifIndex = ifIndex;
++      nDf.WEPDefaultKeyIndex = i + 1;               // index number
++      sprintf ( nDf.UID, "%04d%04d\0", nDf.ifIndex, nDf.WEPDefaultKeyIndex );
++      if ( wep[i].haveKey )
++        strcpy ( nDf.WEPDefaultKeyValue, "*****" );
++      else
++        nDf.WEPDefaultKeyValue[0] = '\0';
++      addList (( char * ) &dfList, ( char * ) &nDf, sizeof ( nDf ));
++    }
++  }
++
++  // dot11PrivacyTable
++  nPr.havePrivacyInvoked = TRUE;
++  nPr.privacyInvoked = 2;                   // 2 => FALSE
++  nPr.haveWEPDefaultKeyID = TRUE;
++  nPr.WEPDefaultKeyID = 0;
++  nPr.haveExcludeUnencrypted = TRUE;
++  nPr.excludeUnencrypted = 2;               // 2 => FALSE
++  if ( wi->has_range ) {
++    if ( ( wi->key_size != 0 ) &&
++        !( wi->key_flags & IW_ENCODE_DISABLED )) {
++       nPr.privacyInvoked = 1;
++       if ( wi->key_flags & IW_ENCODE_RESTRICTED )
++          nPr.excludeUnencrypted = 1;
++       nPr.WEPDefaultKeyID = wepCurrentKey;
++    }
++  }
++
++  // dot11Mac Group
++  // dot11OperationTable
++  if ( wi->has_range ) {
++    nOp.haveRTSThreshold = TRUE;
++    nOp.RTSThreshold = wi->range.max_rts;
++  }
++
++  if ( wi->has_frag && wi->frag.value ) {
++    nOp.haveFragmentationThreshold = TRUE;
++    nOp.fragmentationThreshold = wi->frag.value;
++  }
++
++  // dot11Phy Group
++  // dot11PhyOperationTable
++  if ( strstr ( wi->name, "IEEE 802.11-FS"      )) nPo.PHYType = 1;   // So what if I
++  if ( strstr ( wi->name, "IEEE 802.11-DS"      )) nPo.PHYType = 2;   // made up a couple?
++  if ( strstr ( wi->name, "IEEE 802.11-IR"      )) nPo.PHYType = 3;   
++  if ( strstr ( wi->name, "IEEE 802.11-OFDM"    )) nPo.PHYType = 4;   // 802.11a
++  if ( strstr ( wi->name, "IEEE 802.11-OFDM/DS" )) nPo.PHYType = 5;   // 802.11g
++  if ( strstr ( wi->name, "IEEE 802.11-TURBO"   )) nPo.PHYType = 6;   // Atheros TURBO mode
++  if ( nPo.PHYType ) nPo.havePHYType = TRUE;
++
++  // dot11PhyDSSSTable
++  if ( wi->has_range ) { // && wi->freq <= ( double ) 2483000000 ) {  // DSSS frequencies only
++    for ( i = 0; i < wi->range.num_frequency; i++ ) {
++      if ((( double ) ( wi->range.freq[i].e * 10 ) * ( double ) wi->range.freq[i].m ) == wi->freq ) {
++        nPd.haveCurrentChannel = TRUE;
++        nPd.currentChannel = wi->range.freq[i].i; 
++      }
++    }
++  }
++
++  // dot11SupportedDataRatesTxTable
++  if ( wi->has_range ) {
++    for ( i = 0; i < wi->range.num_bitrates; i++ ) {
++      nRt.ifIndex = ifIndex;
++      nRt.supportedDataRatesTxIndex = i + 1;
++      nRt.supportedDataRatesTxValue = wi->range.bitrate[i] / 500000L;
++      nRt.haveSupportedDataRatesTxValue = TRUE;
++      sprintf ( nRt.UID, "%04d%04d\0", nRt.ifIndex, nRt.supportedDataRatesTxIndex );
++      strcpy ( nRt.ifName, ifName );
++      addList (( char * ) &rtList, ( char * ) &nRt, sizeof ( nRt ));
++    }
++  }
++
++  // dot11SupportedDataRatesRxTable
++  if ( wi->has_range ) {
++    for ( i = 0; i < wi->range.num_bitrates; i++ ) {
++      nRr.ifIndex = ifIndex;
++      nRr.supportedDataRatesRxIndex = i + 1;
++      nRr.supportedDataRatesRxValue = wi->range.bitrate[i] / 500000L;
++      nRr.haveSupportedDataRatesRxValue = TRUE;
++      sprintf ( nRr.UID, "%04d%04d\0", nRr.ifIndex, nRr.supportedDataRatesRxIndex );
++      strcpy ( nRr.ifName, ifName );
++      addList (( char * ) &rrList, ( char * ) &nRr, sizeof ( nRr ));
++    }
++  }
++
++//printf ( "%s max_encoding_tokens: %d\n", 
++//          "loadWiExtTo80211Structs() - ", wi->range.max_encoding_tokens );
++}
++
++/****************************************************************************
++*                                                                           *
++*      loadWiExt() - load wireless extensions structures;                   *
++*                    use ioctl calls and read /proc/net/wireless            *
++*                                                                           *
++****************************************************************************/
++static void loadWiExt ( int skfd, char *ifname, struct wireless_info *wi )
++{
++  struct iwreq wrq;                       // ioctl request structure
++  FILE *fp;
++  char  bfr[1024];
++  char  buffer[sizeof ( iwrange ) * 2]; /* Large enough */
++  char *s, *t;
++  int i, j;
++
++  strncpy ( wrq.ifr_name, ifname, IFNAMSIZ );
++
++  /* Get wireless name */
++  if ( ioctl ( skfd, SIOCGIWNAME, &wrq ) >= 0 ) {
++    strncpy ( wi->name, wrq.u.name, IFNAMSIZ );
++    wi->name[IFNAMSIZ] = '\0';
++  }
++
++  /* Get ranges */    // NOTE: some version checking in iwlib.c
++  memset ( buffer, 0, sizeof ( buffer ));
++  wrq.u.data.pointer = ( caddr_t ) &buffer;
++  wrq.u.data.length = sizeof ( buffer );
++  wrq.u.data.flags = 0;
++  if ( ioctl ( skfd, SIOCGIWRANGE, &wrq ) >= 0 ) {
++    memcpy (( char * ) &wi->range, buffer, sizeof ( iwrange ));
++    wi->has_range = 1;
++  }
++
++  /* Get network ID */
++  if ( ioctl ( skfd, SIOCGIWNWID, &wrq ) >= 0 ) {
++    memcpy ( &wi->nwid, &wrq.u.nwid, sizeof ( iwparam ));
++    wi->has_nwid = 1;
++  }
++
++  /* Get frequency / channel */         // THIS NUMBER LOOKS FUNNY
++  if ( ioctl ( skfd, SIOCGIWFREQ, &wrq ) >= 0 ) {
++    wi->has_freq = 1;
++    wi->freq = (( double ) wrq.u.freq.m ) * pow ( 10, wrq.u.freq.e );
++  }
++
++  /* Get sensitivity */
++  if ( ioctl ( skfd, SIOCGIWSENS, &wrq ) >= 0 ) {
++    wi->has_sens = 1;
++    memcpy ( &wi->sens, &wrq.u.sens, sizeof ( iwparam ));
++  }
++
++  /* Get encryption information */
++  wrq.u.data.pointer = ( caddr_t ) &wi->key;
++  wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
++  wrq.u.data.flags = 0;
++  if ( ioctl ( skfd, SIOCGIWENCODE, &wrq ) >= 0 ) {
++    wi->has_key = 1;
++    wi->key_size = wrq.u.data.length;
++    wi->key_flags = wrq.u.data.flags;
++    wepCurrentKey = wrq.u.data.flags & IW_ENCODE_INDEX;
++  }
++
++  for ( i = 0; i < wi->range.max_encoding_tokens; i++ ) {
++    wrq.u.data.pointer = ( caddr_t ) &wi->key;
++    wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
++    wrq.u.data.flags = i;
++    if ( ioctl ( skfd, SIOCGIWENCODE, &wrq ) >= 0 ) {
++      if ( ( wrq.u.data.length != 0 ) &&
++          !( wrq.u.data.flags & IW_ENCODE_DISABLED )) {
++        wep[i].len = wrq.u.data.length;
++        wep[i].haveKey = TRUE;
++        t = wep[i].key;
++        for ( j = 0; j < wrq.u.data.length; j++ ) {
++          if (( j & 0x1 ) == 0 && j != 0 )
++        	  strcpy ( t++, "-");
++          sprintf ( t, "%.2X", wi->key[j] );
++          t += 2;
++        }
++        t = '\0';
++      }
++    }
++  }
++
++  /* Get ESSID */
++  wrq.u.essid.pointer = ( caddr_t ) &wi->essid;
++  wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
++  wrq.u.essid.flags = 0;
++  if ( ioctl ( skfd, SIOCGIWESSID, &wrq ) >= 0 ) {
++    wi->has_essid = 1;
++    wi->essid_on = wrq.u.data.flags;
++  }
++
++  /* Get AP address */
++  if ( ioctl ( skfd, SIOCGIWAP, &wrq ) >= 0 ) {
++    wi->has_ap_addr = 1;
++    memcpy ( &wi->ap_addr, &wrq.u.ap_addr, sizeof ( sockaddr ));
++  }
++
++  /* Get NickName */
++  wrq.u.essid.pointer = ( caddr_t ) &wi->nickname;
++  wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
++  wrq.u.essid.flags = 0;
++  if ( ioctl ( skfd, SIOCGIWNICKN, &wrq ) >= 0 ) {
++    if ( wrq.u.data.length > 1 )
++      wi->has_nickname = 1;
++  }
++
++  /* Get bit rate */
++  if ( ioctl ( skfd, SIOCGIWRATE, &wrq ) >= 0 ) {
++    wi->has_bitrate = 1;
++    memcpy ( &wi->bitrate, &wrq.u.bitrate, sizeof ( iwparam ));
++  }
++
++  /* Get RTS threshold */
++  if ( ioctl ( skfd, SIOCGIWRTS, &wrq ) >= 0 ) {
++    wi->has_rts = 1;
++    memcpy ( &wi->rts, &wrq.u.rts, sizeof ( iwparam ));
++  }
++
++  /* Get fragmentation threshold */
++  if ( ioctl ( skfd, SIOCGIWFRAG, &wrq ) >= 0 ) {
++      wi->has_frag = 1;
++      memcpy ( &wi->frag, &wrq.u.frag, sizeof ( iwparam ));
++    }
++
++  /* Get operation mode */
++  if ( ioctl ( skfd, SIOCGIWMODE, &wrq ) >= 0 ) {
++      wi->mode = wrq.u.mode;
++      if ( wi->mode < IW_NUM_OPER_MODE && wi->mode >= 0 )
++        wi->has_mode = 1;
++  }
++
++  /* Get Power Management settings */                 // #if WIRELESS_EXT > 9
++  wrq.u.power.flags = 0;
++  if ( ioctl ( skfd, SIOCGIWPOWER, &wrq ) >= 0 ) {
++    wi->has_power = 1;
++    memcpy ( &wi->power, &wrq.u.power, sizeof ( iwparam ));
++  }
++
++  /* Get retry limit/lifetime */                      // #if WIRELESS_EXT > 10
++  if ( ioctl ( skfd, SIOCGIWRETRY, &wrq ) >= 0 ) {    
++    wi->has_retry = 1;
++    memcpy ( &wi->retry, &wrq.u.retry, sizeof ( iwparam ));
++  }
++
++  /* Get stats */                                     // #if WIRELESS_EXT > 11
++  wrq.u.data.pointer = ( caddr_t ) &wi->stats;
++  wrq.u.data.length = 0;
++  wrq.u.data.flags = 1;   /* Clear updated flag */
++  if ( ioctl ( skfd, SIOCGIWSTATS, &wrq ) < 0 )
++    wi->has_stats = 1;
++
++  if ( !wi->has_stats ) {                        // no ioctl support, go to file
++    fp = fopen ( PROC_NET_WIRELESS, "r" );
++    if ( fp ) {
++      while ( fgets ( bfr, sizeof ( bfr ), fp )) {
++        bfr [ sizeof ( bfr ) - 1 ] = '\0';        // no buffer overruns here!
++        strtok (( char * ) &bfr, "\n" );          // '\n' => '\0'
++        if ( strstr ( bfr, ifname ) && strstr ( bfr, ":" )) {
++          wi->has_stats = 1;
++          s = bfr;
++          s = strchr ( s, ':' ); s++;             /* Skip ethX:   */
++          s = strtok ( s, " " );                  /* ' ' => '\0'  */
++          sscanf ( s, "%X", &wi->stats.status ); // status 
++
++          s = strtok ( NULL, " " );               // link quality
++          if ( strchr ( s, '.' ) != NULL )
++            wi->stats.qual.updated |= 1;
++          sscanf ( s, "%d", &wi->stats.qual.qual );
++
++          s = strtok ( NULL, " " );               // signal level
++          if ( strchr ( s,'.' ) != NULL )
++            wi->stats.qual.updated |= 2;
++          sscanf ( s, "%d", &wi->stats.qual.level );
++
++          s = strtok ( NULL, " " );               // noise level
++          if ( strchr ( s, '.' ) != NULL )
++            wi->stats.qual.updated += 4;
++          sscanf ( s, "%d", &wi->stats.qual.noise );
++
++          s = strtok ( NULL, " " ); sscanf ( s, "%d", &wi->stats.discard.nwid     );
++          s = strtok ( NULL, " " ); sscanf ( s, "%d", &wi->stats.discard.code     );
++          s = strtok ( NULL, " " ); sscanf ( s, "%d", &wi->stats.discard.fragment );
++          s = strtok ( NULL, " " ); sscanf ( s, "%d", &wi->stats.discard.retries  );
++          s = strtok ( NULL, " " ); sscanf ( s, "%d", &wi->stats.discard.misc     );
++          s = strtok ( NULL, " " ); sscanf ( s, "%d", &wi->stats.miss.beacon      );
++        }
++      }
++      fclose ( fp );
++    }
++  }
++
++// printf ( "%s bfr: %s\n", "loadTables()", bfr );
++}
++
++/****************************************************************************
++*                                                                           *
++*       displayWiExt() - show what I got from Wireless Extensions           *
++*                                                                           *
++****************************************************************************/
++static void displayWiExt ( struct wireless_info info )
++{
++#ifdef DISPLAYWIEXT
++  int i;
++  char title[] = "displayWiExt() -";
++
++  printf ( "========================================\n" );
++  printf ( "===> Wireless Extension IOCTL calls <===\n" );
++  printf ( "========================================\n" );
++
++  if ( strlen ( info.name ))
++    printf ( "%s name: %s\n", "SIOCGIWNAME", info.name );
++  else
++    printf ( "%s\n", "no info.name support" );
++
++  if ( info.has_nickname = 1 )
++    printf ( "%s nickname: %s\n", "SIOCGIWNICKN", info.nickname );
++  else
++    printf ( "%s %s\n", "SIOCGIWNICKN", " ===> no info.nickname support" );
++
++  if ( info.has_essid ) 
++    printf ( "%s essid_on: %d essid: %s\n", "SIOCGIWESSID", info.essid_on, info.essid );
++  else
++    printf ( "%s %s\n", "SIOCGIWESSID", " ===> no info.essid support" );
++
++  if ( info.has_range ) {
++    printf ( "%s throughput: %d\n",           "SIOCGIWRANGE", info.range.throughput );
++    printf ( "%s min_nwid: %d\n",             "SIOCGIWRANGE", info.range.min_nwid  );
++    printf ( "%s max_nwid: %d\n",             "SIOCGIWRANGE", info.range.max_nwid  );
++    printf ( "%s sensitivity: %d\n",          "SIOCGIWRANGE", info.range.sensitivity );
++    printf ( "%s num_bitrates: %d\n",         "SIOCGIWRANGE", info.range.num_bitrates );
++    for ( i = 0; i < info.range.num_bitrates; i++ ) 
++      printf ( "%s bitrate[%d]: %d\n",        "SIOCGIWRANGE", i, info.range.bitrate[i]  );
++    printf ( "%s min_rts: %d\n",              "SIOCGIWRANGE", info.range.min_rts );
++    printf ( "%s max_rts: %d\n",              "SIOCGIWRANGE", info.range.max_rts );
++    printf ( "%s min_frag: %d\n",             "SIOCGIWRANGE", info.range.min_frag );
++    printf ( "%s max_frag: %d\n",             "SIOCGIWRANGE", info.range.max_frag );
++    printf ( "%s min_pmp: %d\n",              "SIOCGIWRANGE", info.range.min_pmp );
++    printf ( "%s max_pmp: %d\n",              "SIOCGIWRANGE", info.range.max_pmp );
++    printf ( "%s min_pmt: %d\n",              "SIOCGIWRANGE", info.range.min_pmt );
++    printf ( "%s max_pmt: %d\n",              "SIOCGIWRANGE", info.range.max_pmt );
++    printf ( "%s pmp_flags: %d\n",            "SIOCGIWRANGE", info.range.pmp_flags );
++    printf ( "%s pmt_flags: %d\n",            "SIOCGIWRANGE", info.range.pmt_flags );
++    printf ( "%s pm_capa: %d\n",              "SIOCGIWRANGE", info.range.pm_capa );
++    printf ( "%s num_encoding_sizes: %d\n",   "SIOCGIWRANGE", info.range.num_encoding_sizes );
++    for ( i = 0; i < info.range.num_encoding_sizes; i++ ) 
++      printf ( "%s encoding_size[%d]: %d\n",  "SIOCGIWRANGE", i, info.range.encoding_size[i]  );
++    printf ( "%s max_encoding_tokens: %d\n",  "SIOCGIWRANGE", info.range.max_encoding_tokens );
++//  printf ( "%s encoding_login_index: %d\n", "SIOCGIWRANGE", info.range.encoding_login_index );
++    printf ( "%s txpower_capa: %d\n",         "SIOCGIWRANGE", info.range.txpower_capa );
++    printf ( "%s num_txpower: %d dBm\n",      "SIOCGIWRANGE", info.range.num_txpower );
++    for ( i = 0; i < info.range.num_txpower; i++ ) 
++      printf ( "%s txpower[%d]: %d\n",        "SIOCGIWRANGE", i, info.range.txpower[i]  );
++    printf ( "%s we_version_compiled: %d\n",  "SIOCGIWRANGE", info.range.we_version_compiled );
++    printf ( "%s we_version_source: %d\n",    "SIOCGIWRANGE", info.range.we_version_source );
++    printf ( "%s retry_capa: %d\n",           "SIOCGIWRANGE", info.range.retry_capa );
++    printf ( "%s retry_flags: %d\n",          "SIOCGIWRANGE", info.range.retry_flags );
++    printf ( "%s r_time_flags: %d\n",         "SIOCGIWRANGE", info.range.r_time_flags );
++    printf ( "%s min_retry: %d\n",            "SIOCGIWRANGE", info.range.min_retry );
++    printf ( "%s max_retry: %d\n",            "SIOCGIWRANGE", info.range.max_retry );
++    printf ( "%s min_r_time: %d\n",           "SIOCGIWRANGE", info.range.min_r_time );
++    printf ( "%s max_r_time: %d\n",           "SIOCGIWRANGE", info.range.max_r_time );
++    printf ( "%s num_channels: %d\n",         "SIOCGIWRANGE", info.range.num_channels );
++    printf ( "%s num_frequency: %d\n",        "SIOCGIWRANGE", info.range.num_frequency );
++    for ( i = 0; i < info.range.num_frequency; i++ ) 
++      printf ( "%s freq[%d].i: %d freq[%d].e: %d freq[%d].m: %d\n", "SIOCGIWRANGE", 
++                i, info.range.freq[i].i, i, info.range.freq[i].e, i, info.range.freq[i].m );
++  }
++  else
++    printf ( "%s %s\n", "SIOCGIWRANGE", " ===> no info.range support" );
++
++  if ( info.has_nwid ) 
++    printf ( "%s nwid - disabled: %d value: %X\n", "SIOCGIWNWID", info.nwid.disabled, info.nwid.value );
++  else
++    printf ( "%s %s\n", "SIOCGIWNWID", " ===> no info.nwid support" );
++
++  if ( info.has_freq ) {
++//  printf ( "%s freq: %g\n", "SIOCGIWFREQ", info.freq / GIGA );
++    printf ( "%s freq: %g\n", "SIOCGIWFREQ", info.freq );
++  }
++  else
++    printf ( "%s %s\n", "SIOCGIWFREQ", " ===> no info.freq support" );
++
++  if ( info.has_sens )
++    printf ( "%s sens: %d\n", "SIOCGIWSENS", info.sens );
++  else
++    printf ( "%s %s\n", "SIOCGIWSENS", " ===> no info.sens support" );
++
++  if ( info.has_key ) {
++    printf ( "%s key_size: %d key_flags: %d wepCurrentKey: %d\n", 
++              "SIOCGIWENCODE", info.key_size, info.key_flags, wepCurrentKey );
++    printf ( "%s MODE: %d DISABLED: %d INDEX: %d OPEN: %d RESTRICTED: %d NOKEY: %d TEMP: %d\n",
++              "SIOCGIWENCODE",                           info.key_flags & IW_ENCODE_MODE,
++              info.key_flags & IW_ENCODE_DISABLED ? 1:0, info.key_flags & IW_ENCODE_INDEX,
++              info.key_flags & IW_ENCODE_OPEN     ? 1:0, info.key_flags & IW_ENCODE_RESTRICTED ? 1:0,
++              info.key_flags & IW_ENCODE_NOKEY    ? 1:0, info.key_flags & IW_ENCODE_TEMP       ? 1:0 );
++  }
++  else
++    printf ( "%s %s\n", "SIOCGIWENCODE", " ===> no info.key support" );
++
++  for ( i = 0; i < MAX_WEP_KEYS; i++ ) {
++    if ( wep[i].haveKey )
++      printf ( "%s wep[%d].len: %d wep[%d].key: %s\n", 
++                "SIOCGIWENCODE", i, wep[i].len, i, wep[i].key );
++  }
++
++  if ( info.has_ap_addr )
++    printf ( "%s ap_addr.sa_data: %02X:%02X:%02X:%02X:%02X:%02X ap_addr.sa_family: %d\n", 
++              "SIOCGIWAP",  ( UCHAR ) info.ap_addr.sa_data[0], ( UCHAR ) info.ap_addr.sa_data[1], 
++                            ( UCHAR ) info.ap_addr.sa_data[2], ( UCHAR ) info.ap_addr.sa_data[3], 
++                            ( UCHAR ) info.ap_addr.sa_data[4], ( UCHAR ) info.ap_addr.sa_data[5], 
++                                      info.ap_addr.sa_family );
++  else
++    printf ( "%s %s\n", "SIOCGIWAP", " ===> no ap_addr information" );
++
++  if ( info.has_bitrate )
++    printf ( "%s bitrate: %d value: %d fixed: %d disabled: %d flags: %d\n", 
++              "SIOCGIWRATE", info.bitrate, info.bitrate.value, info.bitrate.fixed, 
++                             info.bitrate.disabled, info.bitrate.flags );
++  else
++    printf ( "%s %s\n", "SIOCGIWRATE", " ===> no info.bitrate support" );
++
++  if ( info.has_rts )
++    printf ( "%s rts: %d\n", "SIOCGIWRTS", info.rts );
++  else
++    printf ( "%s %s\n", "SIOCGIWRTS", " ===> no info.rts support" );
++
++  if ( info.has_frag )
++    printf ( "%s frag: %d\n", "SIOCGIWFRAG", info.frag );
++  else
++    printf ( "%s %s\n", "SIOCGIWFRAG", " ===> no info.frag support" );
++
++  if ( info.has_mode ) 
++    printf ( "%s mode: %d\n", "SIOCGIWMODE", info.mode );
++  else
++    printf ( "%s %s\n", "SIOCGIWMODE", " ===> no info.mode support" );
++
++  if ( info.has_power ) {
++    printf ( "%s power: %d\n", "SIOCGIWPOWER", info.power );
++    printf ( "%s disabled: %d MIN: %d MAX: %d TIMEOUT: %d RELATIVE: %d\n",
++              "SIOCGIWPOWER",
++              info.power.disabled                  ? 1:0, 
++              info.power.flags & IW_POWER_MIN      ? 1:0, 
++              info.power.flags & IW_POWER_MAX      ? 1:0, 
++              info.power.flags & IW_POWER_TIMEOUT  ? 1:0, 
++              info.power.flags & IW_POWER_RELATIVE ? 1:0 ); 
++    printf ( "%s UNICAST: %d MULTICAST: %d ALL: %d FORCE: %d REPEATER: %d\n",
++              "SIOCGIWPOWER",
++              info.power.flags & IW_POWER_UNICAST_R   ? 1:0, 
++              info.power.flags & IW_POWER_MULTICAST_R ? 1:0, 
++              info.power.flags & IW_POWER_ALL_R       ? 1:0, 
++              info.power.flags & IW_POWER_FORCE_S     ? 1:0, 
++              info.power.flags & IW_POWER_REPEATER    ? 1:0 ); 
++  }
++  else
++    printf ( "%s %s\n", "SIOCGIWPOWER", " ===> no info.power support" );
++
++  if ( info.has_retry )
++    printf ( "%s retry: %d\n", "SIOCGIWRETRY", info.retry );
++  else
++    printf ( "%s %s\n", "SIOCGIWRETRY", " ===> no info.retry support" );
++
++  if ( info.has_stats ) {
++    printf ( "%s status: %d\n",           "SIOCGIWSTATS", info.stats.status           );
++    printf ( "%s qual.level: %d\n",       "SIOCGIWSTATS", info.stats.qual.level       );
++    printf ( "%s qual.noise: %d\n",       "SIOCGIWSTATS", info.stats.qual.noise       );
++    printf ( "%s qual.qual: %d\n",        "SIOCGIWSTATS", info.stats.qual.qual        );
++    printf ( "%s qual.updated: %d\n",     "SIOCGIWSTATS", info.stats.qual.updated     );
++    printf ( "%s discard.code: %d\n",     "SIOCGIWSTATS", info.stats.discard.code     );
++    printf ( "%s discard.fragment: %d\n", "SIOCGIWSTATS", info.stats.discard.fragment );
++    printf ( "%s discard.misc: %d\n",     "SIOCGIWSTATS", info.stats.discard.misc     );
++    printf ( "%s discard.nwid: %d\n",     "SIOCGIWSTATS", info.stats.discard.nwid     );
++    printf ( "%s discard.retries: %d\n",  "SIOCGIWSTATS", info.stats.discard.retries  );
++    printf ( "%s miss.beacon: %d\n",      "SIOCGIWSTATS", info.stats.miss.beacon      );
++  }
++  else
++    printf ( "%s %s\n", "SIOCGIWSTATS", " ===> no info.stats support" );
++
++  if ( info.txpower.flags & IW_TXPOW_MWATT )
++    printf ( "%s txpower1: %d dBm disabled: %d fixed: %d flags: %d\n", "SIOCGIWRANGE", 
++      mWatt2dbm ( info.txpower.value ), info.txpower.disabled, info.txpower.fixed, info.txpower.flags);
++  else
++    printf ( "%s txpower2: %d dBm disabled: %d fixed: %d flags: %d\n", "SIOCGIWRANGE", info.txpower.value, info.txpower.disabled, info.txpower.fixed, info.txpower.flags );
++
++  if ( info.has_range ) 
++    if ( info.sens.value < 0 )
++      printf ( "%s sens: %d dBm\n", "SIOCGIWRANGE", info.sens.value );
++    else
++      printf ( "%s sens: %d/%d\n", "SIOCGIWRANGE", info.sens.value, info.range.sensitivity );
++
++  if ( info.has_range && ( info.stats.qual.level != 0 ))
++      if ( info.stats.qual.level > info.range.max_qual.level )
++        /* Statistics are in dBm (absolute power measurement) */
++        printf ( "%s Quality: %d/%d Signal level: %d dBm Noise level: %d dBm\n",
++                  "SIOCGIWRANGE",
++                  info.stats.qual.qual, info.range.max_qual.qual,
++                  info.stats.qual.level - 0x100,
++                  info.stats.qual.noise - 0x100 );
++      else
++        printf (  "%s Quality: %d/%d Signal level: %d/%d Noise level: %d/%d",
++                  "SIOCGIWRANGE",
++                  info.stats.qual.qual,  info.range.max_qual.qual,
++                  info.stats.qual.level, info.range.max_qual.level,
++                  info.stats.qual.noise, info.range.max_qual.noise );
++
++#endif // #ifdef DISPLAYWIEXT
++}
++
++/****************************************************************************
++*                                                                           *
++*                        Linked List Functions                              *
++*                                                                           *
++****************************************************************************/
++/****************************************************************************
++*                                                                           *
++*                addList() - add an entry to a linked list                  *
++*                                                                           *
++****************************************************************************/
++static void 
++addList ( char *l, char *data, int len  )
++{
++  char uid[256];
++  LIST_HEAD ( , avNode ) *list;       
++
++  // NOTE: this assumes the UID is at the beginning of the 
++  //       data structure and that UIDs are strings
++  
++  list = ( LIST_HEAD ( , avNode ) * ) l;            // NOTE: don't know how to get 
++  strcpy ( uid, data );                             //  rid of compiler warning on
++                                                    //  LISTHEAD typecast
++  // create a new node and the data that goes in it
++  newNode = malloc ( sizeof ( struct avNode ));
++  newNode->data = malloc ( len );
++  memcpy ( newNode->data, data, len );
++
++  // this deals with an empty list
++  if ( LIST_EMPTY ( list )) {
++    LIST_INSERT_HEAD ( list, newNode, nodes );
++    return;
++  }
++
++  // this deals with UIDs that match
++  for ( np = LIST_FIRST ( list ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    if ( strncmp ( uid, np->data, strlen ( uid )) == 0 ) {                      // found matching UID
++      LIST_INSERT_AFTER ( np, newNode, nodes );
++      if ( np->data )
++        free ( np->data );
++      LIST_REMOVE ( np, nodes );
++      free ( np );
++      return;
++    }
++  }
++
++  // this deals with inserting a new UID in the list
++  for ( np = LIST_FIRST ( list ); np != NULL; np = LIST_NEXT ( np, nodes )) {
++    lastNode = np;
++    if ( strncmp ( np->data, uid, strlen ( uid )) > 0 ) {                       // old ID > new ID AND
++      LIST_INSERT_BEFORE ( np, newNode, nodes );
++      return;
++    }
++  }
++
++  // this deals with a UID that needs to go on the end of the list
++  LIST_INSERT_AFTER ( lastNode, newNode, nodes );
++
++  return;
++}
++
++/****************************************************************************
++*                                                                           *
++*              initLists() - initialize all the linked lists                *
++*                                                                           *
++****************************************************************************/
++static void initLists()
++{
++  LIST_INIT ( &scList );  LIST_INIT ( &aaList );  LIST_INIT ( &dfList );
++  LIST_INIT ( &kmList );  LIST_INIT ( &prList );
++  LIST_INIT ( &opList );  LIST_INIT ( &coList );
++  LIST_INIT ( &gaList );  LIST_INIT ( &riList );  LIST_INIT ( &poList );
++  LIST_INIT ( &paList );  LIST_INIT ( &ptList );  LIST_INIT ( &pfList );
++  LIST_INIT ( &pdList );  LIST_INIT ( &piList );  LIST_INIT ( &rdList );
++  LIST_INIT ( &alList );  LIST_INIT ( &rtList );  LIST_INIT ( &rrList );
++}
++/****************************************************************************
++*                                                                           *
++*                 flushLists() - flush all linked lists                     *
++*                                                                           *
++****************************************************************************/
++static void flushLists()
++{
++  flushList (( char * ) &scList );  flushList (( char * ) &aaList );
++  flushList (( char * ) &dfList );  flushList (( char * ) &kmList );
++  flushList (( char * ) &prList );
++  flushList (( char * ) &opList );  flushList (( char * ) &coList );
++  flushList (( char * ) &gaList );  flushList (( char * ) &riList );
++  flushList (( char * ) &poList );  flushList (( char * ) &paList );
++  flushList (( char * ) &ptList );  flushList (( char * ) &pfList );
++  flushList (( char * ) &pdList );  flushList (( char * ) &piList );
++  flushList (( char * ) &rdList );  flushList (( char * ) &alList );
++  flushList (( char * ) &rtList );  flushList (( char * ) &rrList );
++}
++
++/****************************************************************************
++*                                                                           *
++*                   flushList() - flush a linked list                       *
++*                                                                           *
++****************************************************************************/
++static void flushList ( char *l )
++{
++  LIST_HEAD ( , avNode ) *list;
++  
++  list = ( LIST_HEAD ( , avNode ) * ) l;    // NOTE: don't know how to get 
++  while ( !LIST_EMPTY ( list )) {           //  rid of compiler warning on
++    np = LIST_FIRST ( list );               //  LISTHEAD typecast
++    if ( np->data )
++      free ( np->data );
++    LIST_REMOVE ( np, nodes );
++    free ( np );
++  }
++}
++
++/****************************************************************************
++*                                                                           *
++*                            Utility Functions                              *
++*                                                                           *
++****************************************************************************/
++/****************************************************************************
++*                                                                           *
++*        The following two routines were taken directly from iwlib.c        *
++*                                                                           *
++****************************************************************************/
++ /*
++ * Open a socket.
++ * Depending on the protocol present, open the right socket. The socket
++ * will allow us to talk to the driver.
++ */
++static int openSocket ( void )
++{
++  static const int families[] = {
++    AF_INET, AF_IPX, AF_AX25, AF_APPLETALK
++  };
++  unsigned int  i;
++  int   sock;
++
++  /*
++   * Now pick any (exisiting) useful socket family for generic queries
++   * Note : don't open all the socket, only returns when one matches,
++   * all protocols might not be valid.
++   * Workaround by Jim Kaba <jkaba@sarnoff.com>
++   * Note : in 99% of the case, we will just open the inet_sock.
++   * The remaining 1% case are not fully correct...
++   */
++
++  /* Try all families we support */
++  for(i = 0; i < sizeof(families)/sizeof(int); ++i) {
++      /* Try to open the socket, if success returns it */
++      sock = socket(families[i], SOCK_DGRAM, 0);
++      if(sock >= 0)
++  return sock;
++  }
++
++  return -1;
++}
++
++/*------------------------------------------------------------------*/
++/*
++ * Convert a value in milliWatt to a value in dBm.
++ */
++static int mWatt2dbm ( int in )
++{
++#ifdef WE_NOLIBM
++  /* Version without libm : slower */
++  double  fin = (double) in;
++  int   res = 0;
++
++  /* Split integral and floating part to avoid accumulating rounding errors */
++  while(fin > 10.0)
++    {
++      res += 10;
++      fin /= 10.0;
++    }
++  while(fin > 1.000001) /* Eliminate rounding errors, take ceil */
++    {
++      res += 1;
++      fin /= LOG10_MAGIC;
++    }
++  return(res);
++#else /* WE_NOLIBM */
++  /* Version with libm : faster */
++  return((int) (ceil(10.0 * log10((double) in))));
++#endif  /* WE_NOLIBM */
++}
++
++/****************************************************************************
++*                                                                           *
++*                 htob - converts hex string to binary                      *
++*                                                                           *
++****************************************************************************/
++static char *htob ( char *s )
++{
++    char nibl, *byt;
++    static char bin[20];
++
++    byt = bin;
++
++    while ((nibl = *s++) && nibl != ' ') {    /* While not end of string. */
++      nibl -= ( nibl > '9') ?  ('A' - 10): '0';
++      *byt = nibl << 4;                              /* place high nibble */
++      if((nibl = *s++) && nibl != ' ') {
++        nibl -= ( nibl > '9') ?  ('A' - 10): '0';
++        *byt |= nibl;                                /*  place low nibble */
++      }
++      else break;
++      ++byt;
++    }
++    *++byt = '\0';
++    return ( bin );
++}
++
++/****************************************************************************
++*                                                                           *
++*           hasChanged() - see if area has been changed from NULLs          *
++*                                                                           *
++****************************************************************************/
++static int hasChanged ( char *loc, int len )
++{
++  char *wrk;
++  int changed = TRUE;
++
++  wrk = malloc ( len );
++  memset ( wrk, 0, len );
++  if ( memcmp ( loc, wrk, len ) == 0 )
++    changed = FALSE;
++  free ( wrk );
++
++  return ( changed );
++}
++
+--- /dev/null
++++ b/agent/mibgroup/ieee802dot11.h
+@@ -0,0 +1,730 @@
++/****************************************************************************
++*                                                                           *
++*  File Name:           ieee802dot11.h                                      *
++*  Used By:                                                                 *
++*                                                                           *
++*  Operating System:                                                        *
++*  Purpose:                                                                 *
++*                                                                           *
++*  Comments:                                                                *
++*                                                                           *
++*  Author:              Larry Simmons                                       *
++*                       lsimmons@avantcom.com                               *
++*                       www.avantcom.com                                    *
++*                                                                           *
++*  Creation Date:       09/02/03                                            *
++*                                                                           *
++*   Ver    Date   Inits Modification                                        *
++*  ----- -------- ----- ------------                                        *
++*  0.0.1 09/02/03  LRS  created                                             *
++*  0.0.2 09/24/03  LRS  wouldn't build after fresh ./configure              *
++****************************************************************************/
++/* This file was generated by mib2c and is intended for use as a mib module
++  for the ucd-snmp snmpd agent. */
++#ifndef _MIBGROUP_IEEE802DOT11_H
++#define _MIBGROUP_IEEE802DOT11_H
++/* we may use header_generic and header_simple_table from the util_funcs module */
++
++/****************************************************************************
++*                               Includes                                    *
++****************************************************************************/
++#include <sys/queue.h>
++
++/****************************************************************************
++*                             Linked List Defines                           *
++****************************************************************************/
++// here are some Linked List MACROS I wanted to use, 
++// but curiously were not in /usr/includes/sys/queue.h
++
++#ifndef LIST_EMPTY
++  #define	LIST_EMPTY(head)	((head)->lh_first == NULL)
++#endif
++
++#ifndef LIST_NEXT
++  #define	LIST_NEXT(elm, field)	((elm)->field.le_next)
++#endif
++
++#ifndef LIST_INSERT_BEFORE
++  #define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
++	  (elm)->field.le_prev = (listelm)->field.le_prev;		\
++	  LIST_NEXT((elm), field) = (listelm);				\
++	  *(listelm)->field.le_prev = (elm);				\
++	  (listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
++  } while (0)
++#endif
++
++#ifndef LIST_FIRST
++  #define	LIST_FIRST(head)	((head)->lh_first)
++#endif
++
++/****************************************************************************
++*                             802.11 MIB Defines                            *
++****************************************************************************/
++#define SYS_STRING_LEN                     256
++#define MACADDR_LEN                        ( 6 * 2 ) + 5
++#define OPER_RATE_SET_LEN                  126
++#define MAN_OUI_LEN                        ( 3 * 2 ) + 2
++#define WEP_STR_LEN                         64
++#define SNMP_STR_LEN                       128
++#define TEXT_LEN                            80
++#define IFINDEX_LEN                          4
++#define IFNAME_LEN                          16
++#define MAX_WEP_KEYS                         4
++
++#define AUTHENICATION_ALGORITHMS_INDEX_LEN   4
++#define WEP_DEFAULT_KEY_INDEX_LEN            4
++#define WEP_KEY_MAPPING_INDEX_LEN            4
++#define GROUP_ADDRESS_INDEX_LEN              4
++#define REG_DOMAIN_SUPPORT_INDEX_LEN         4
++#define ANTENNA_LIST_INDEX_LEN               4
++#define SUPPORTED_DATA_RATES_TX_INDEX_LEN    4
++#define SUPPORTED_DATA_RATES_RX_INDEX_LEN    4
++
++#define SC_UID_LEN  IFINDEX_LEN
++#define AA_UID_LEN  IFINDEX_LEN + AUTHENICATION_ALGORITHMS_INDEX_LEN
++#define DF_UID_LEN  IFINDEX_LEN + WEP_DEFAULT_KEY_INDEX_LEN
++#define KM_UID_LEN  IFINDEX_LEN + WEP_KEY_MAPPING_INDEX_LEN
++#define PR_UID_LEN  IFINDEX_LEN
++#define OP_UID_LEN  IFINDEX_LEN
++#define CO_UID_LEN  IFINDEX_LEN
++#define GA_UID_LEN  IFINDEX_LEN + GROUP_ADDRESS_INDEX_LEN
++#define RI_UID_LEN  IFINDEX_LEN
++#define PO_UID_LEN  IFINDEX_LEN
++#define PA_UID_LEN  IFINDEX_LEN
++#define PT_UID_LEN  IFINDEX_LEN
++#define PF_UID_LEN  IFINDEX_LEN
++#define PD_UID_LEN  IFINDEX_LEN
++#define PI_UID_LEN  IFINDEX_LEN
++#define RD_UID_LEN  IFINDEX_LEN + REG_DOMAIN_SUPPORT_INDEX_LEN
++#define AL_UID_LEN  IFINDEX_LEN + ANTENNA_LIST_INDEX_LEN
++#define RT_UID_LEN  IFINDEX_LEN + SUPPORTED_DATA_RATES_TX_INDEX_LEN
++#define RR_UID_LEN  IFINDEX_LEN + SUPPORTED_DATA_RATES_RX_INDEX_LEN
++
++/****************************************************************************
++*                           Linked List Structure                           *
++****************************************************************************/
++static struct avNode {  
++  LIST_ENTRY ( avNode ) nodes; 
++  char *data;                                 // pointer to data
++};
++
++typedef LIST_HEAD ( , avNode ) avList_t;
++
++/****************************************************************************
++*                          802.11 MIB structures                            *
++****************************************************************************/
++/****************************************************************************
++*                             dot11Smt Group                                *
++****************************************************************************/
++/****************************************************************************
++*                          dot11StationConfigTable                          *
++****************************************************************************/
++static struct scTbl_data {
++
++  char  UID       [ SC_UID_LEN + 1 ];               // unique ID
++  char  ifName    [ IFNAME_LEN + 1 ];               // ifName of card
++
++  long  ifIndex;                                    // ifindex of card
++
++  char  stationID [ MACADDR_LEN + 1 ];              // Default actual MacAddr
++  long  mediumOccupancyLimit;
++  long  CFPPollable;
++  long  CFPPeriod;
++  long  maxDuration;
++  long  authenticationResponseTimeOut;
++  long  privacyOptionImplemented;
++  long  powerManagementMode;
++  char  desiredSSID             [ SNMP_STR_LEN + 1 ];
++  long  desiredBSSType;
++  char  operationalRateSet      [ OPER_RATE_SET_LEN + 1];
++  long  beaconPeriod;
++  long  DTIMPeriod;
++  long  associationResponseTimeOut;
++  long  disAssociationReason;
++  char  disAssociationStation   [ MACADDR_LEN + 1 ];
++  long  deAuthenticationReason;
++  char  deAuthenticationStation [ MACADDR_LEN + 1 ];
++  long  authenticateFailStatus;
++  char  authenticateFailStation [ MACADDR_LEN + 1 ];
++
++  long  haveStationID;
++  long  haveMediumOccupancyLimit;
++  long  haveCFPPollable;
++  long  haveCFPPeriod;
++  long  haveMaxDuration;
++  long  haveAuthenticationResponseTimeOut;
++  long  havePrivacyOptionImplemented;
++  long  havePowerManagementMode;
++  long  haveDesiredSSID;
++  long  haveDesiredBSSType;
++  long  haveOperationalRateSet;
++  long  haveBeaconPeriod;
++  long  haveDTIMPeriod;
++  long  haveAssociationResponseTimeOut;
++  long  haveDisAssociationReason;
++  long  haveDisAssociationStation;
++  long  haveDeAuthenticationReason;
++  long  haveDeAuthenticationStation;
++  long  haveAuthenticateFailStatus;
++  long  haveAuthenticateFailStation;
++
++} nSc, *sc = &nSc;
++
++static avList_t scList;
++
++/****************************************************************************
++*                    dot11AuthenticationAlgorithmsTable                     *
++****************************************************************************/
++static struct aaTbl_data {
++
++  char  UID       [ AA_UID_LEN + 1 ];
++  char  ifName    [ IFNAME_LEN + 1 ];               // ifName of card
++
++  long  ifIndex;                                    // ifindex of card
++  long  authenticationAlgorithmsIndex;
++
++  long  authenticationAlgorithm;
++  long  authenticationAlgorithmsEnable;
++
++  long  haveAuthenticationAlgorithm;
++  long  haveAuthenticationAlgorithmsEnable;
++
++} nAa, *aa = &nAa;
++
++static avList_t aaList;
++
++/****************************************************************************
++*                           dot11WEPDefaultKeysTable                        *
++****************************************************************************/
++static struct dfTbl_data {
++
++  char  UID       [ DF_UID_LEN + 1 ];
++  char  ifName    [ IFNAME_LEN + 1 ];
++
++  long  ifIndex;                                    // ifindex of card
++  long  WEPDefaultKeyIndex;
++
++  char  WEPDefaultKeyValue [ WEP_STR_LEN + 1 ];
++  long  haveWEPDefaultKeyValue;
++
++} nDf, *df = &nDf;
++
++static avList_t dfList;
++
++/****************************************************************************
++*                          dot11WEPKeyMappingsTable                         *
++****************************************************************************/
++static struct kmTbl_data {
++
++  char  UID       [ KM_UID_LEN + 1 ];
++  char  ifName    [ IFNAME_LEN + 1 ];
++
++  long  ifIndex;
++  long  WEPKeyMappingIndex;
++
++  char  WEPKeyMappingAddress  [ MACADDR_LEN + 1 ];
++  long  WEPKeyMappingWEPOn;
++  char  WEPKeyMappingValue    [ WEP_STR_LEN + 1 ];
++  long  WEPKeyMappingStatus;
++
++  long  haveWEPKeyMappingIndex;
++  long  haveWEPKeyMappingAddress;
++  long  haveWEPKeyMappingWEPOn;
++  long  haveWEPKeyMappingValue;
++  long  haveWEPKeyMappingStatus;
++
++} nKm, *km = &nKm;
++
++static avList_t kmList;
++
++/****************************************************************************
++*                                dot11PrivacyTable                          *
++****************************************************************************/
++static struct prTbl_data {
++
++  char          UID       [ PR_UID_LEN + 1 ];
++  char          ifName    [ IFNAME_LEN + 1 ];
++
++  long          ifIndex;
++
++  long          privacyInvoked;
++  long          WEPDefaultKeyID;
++  long          WEPKeyMappingLength;
++  long          excludeUnencrypted;
++  unsigned long WEPICVErrorCount;
++  unsigned long WEPExcludedCount;
++
++  long          havePrivacyInvoked;
++  long          haveWEPDefaultKeyID;
++  long          haveWEPKeyMappingLength;
++  long          haveExcludeUnencrypted;
++  long          haveWEPICVErrorCount;
++  long          haveWEPExcludedCount;
++
++} nPr, *pr = &nPr;
++
++static avList_t prList;
++
++/****************************************************************************
++*                               dot11Mac Group                              *
++****************************************************************************/
++/****************************************************************************
++*                              dot11OperationTable                          *
++****************************************************************************/
++static struct opTbl_data {
++
++  char  UID       [ OP_UID_LEN + 1 ];                 // unique ID
++  char  ifName    [ IFNAME_LEN + 1 ];                 // ifName of card
++
++  long  ifIndex;                                      // ifindex of card
++
++  char  MACAddress      [ MACADDR_LEN + 1 ];
++  long  RTSThreshold;
++  long  shortRetryLimit;
++  long  longRetryLimit;
++  long  fragmentationThreshold;
++  long  maxTransmitMSDULifetime;
++  long  maxReceiveLifetime;
++  char  manufacturerID  [ SNMP_STR_LEN + 1 ];
++  char  productID       [ SNMP_STR_LEN + 1 ];
++
++  long  haveMACAddress;
++  long  haveRTSThreshold;
++  long  haveShortRetryLimit;
++  long  haveLongRetryLimit;
++  long  haveFragmentationThreshold;
++  long  haveMaxTransmitMSDULifetime;
++  long  haveMaxReceiveLifetime;
++  long  haveManufacturerID;
++  long  haveProductID;
++
++} nOp, *op = &nOp;
++
++static avList_t opList;
++
++/****************************************************************************
++*                            dot11CountersTable                             *
++****************************************************************************/
++static struct coTbl_data {
++
++  char          UID       [ CO_UID_LEN + 1 ];     // unique ID
++  char          ifName    [ IFNAME_LEN + 1 ];     // ifName of card
++
++  long          ifIndex;                          // ifindex of card
++
++  unsigned long  transmittedFragmentCount;
++  unsigned long  multicastTransmittedFrameCount;
++  unsigned long  failedCount;
++  unsigned long  retryCount;
++  unsigned long  multipleRetryCount;
++  unsigned long  frameDuplicateCount;
++  unsigned long  RTSSuccessCount;
++  unsigned long  RTSFailureCount;
++  unsigned long  ACKFailureCount;
++  unsigned long  receivedFragmentCount;
++  unsigned long  multicastReceivedFrameCount;
++  unsigned long  FCSErrorCount;
++  unsigned long  transmittedFrameCount;
++  unsigned long  WEPUndecryptableCount;
++
++  long           haveTransmittedFragmentCount;
++  long           haveMulticastTransmittedFrameCount;
++  long           haveFailedCount;
++  long           haveRetryCount;
++  long           haveMultipleRetryCount;
++  long           haveFrameDuplicateCount;
++  long           haveRTSSuccessCount;
++  long           haveRTSFailureCount;
++  long           haveACKFailureCount;
++  long           haveReceivedFragmentCount;
++  long           haveMulticastReceivedFrameCount;
++  long           haveFCSErrorCount;
++  long           haveTransmittedFrameCount;
++  long           haveWEPUndecryptableCount;
++
++} nCo, *co = &nCo;
++
++static avList_t coList;
++
++/****************************************************************************
++*                        dot11GroupAddressesTable                           *
++****************************************************************************/
++static struct gaTbl_data {
++
++  char  UID       [ GA_UID_LEN + 1 ];
++  char  ifName    [ IFNAME_LEN + 1 ];
++
++  long  ifIndex;                                    // ifindex of card
++  long  groupAddressesIndex;
++
++  char  address   [ MACADDR_LEN + 1 ];
++  long  groupAddressesStatus;
++
++  long  haveAddress;
++  long  haveGroupAddressesStatus;
++
++} nGa, *ga = &nGa;
++
++static avList_t gaList;
++
++/****************************************************************************
++*                               dot11Res Group                              *
++****************************************************************************/
++static char  resourceTypeIDName[] = "RTID";
++static long  haveResourceTypeIDName = 1;
++
++/****************************************************************************
++*                           dot11ResourceInfoTable                          *
++****************************************************************************/
++static struct riTbl_data {
++
++  char  UID       [ RI_UID_LEN + 1 ];               // unique ID
++  char  ifName    [ IFNAME_LEN + 1 ];               // ifName of card
++
++  long  ifIndex;                                    // ifindex of card
++
++  char  manufacturerOUI            [ MAN_OUI_LEN    + 1 ];
++  char  manufacturerName           [ SYS_STRING_LEN + 1 ];
++  char  manufacturerProductName    [ SYS_STRING_LEN + 1 ];
++  char  manufacturerProductVersion [ SYS_STRING_LEN + 1 ];
++
++  char  haveManufacturerOUI;
++  char  haveManufacturerName;
++  char  haveManufacturerProductName;
++  char  haveManufacturerProductVersion;
++
++} nRi, *ri = &nRi;
++
++static avList_t riList;
++
++/****************************************************************************
++*                               dot11Phy Group                              *
++****************************************************************************/
++/****************************************************************************
++*                           dot11PhyOperationTable                          *
++****************************************************************************/
++static struct poTbl_data {
++
++  char  UID       [ PO_UID_LEN + 1 ];               // unique ID
++  char  ifName    [ IFNAME_LEN + 1 ];               // ifName of card
++
++  long  ifIndex;                                    // ifindex of card
++
++  long  PHYType;
++  long  currentRegDomain;
++  long  tempType;
++
++  long  havePHYType;
++  long  haveCurrentRegDomain;
++  long  haveTempType;
++
++} nPo, *po = &nPo;
++
++static avList_t poList;
++
++/****************************************************************************
++*                           dot11PhyAntennaEntry                            *
++****************************************************************************/
++static struct paTbl_data {
++
++  char  UID       [ PA_UID_LEN + 1 ];               // unique ID
++  char  ifName    [ IFNAME_LEN + 1 ];               // ifName of card
++
++  long  ifIndex;                                    // ifindex of card
++
++  long  currentTxAntenna;
++  long  diversitySupport;
++  long  currentRxAntenna;
++
++  long  haveCurrentTxAntenna;
++  long  haveDiversitySupport;
++  long  haveCurrentRxAntenna;
++
++} nPa, *pa = &nPa;
++
++static avList_t paList;
++
++/****************************************************************************
++*                             dot11PhyTxPowerTable                          *
++****************************************************************************/
++static struct ptTbl_data {
++
++  char  UID       [ PT_UID_LEN + 1 ];               // unique ID
++  char  ifName    [ IFNAME_LEN + 1 ];               // ifName of card
++
++  long  ifIndex;                                    // ifindex of card
++
++  long  numberSupportedPowerLevels;
++  long  TxPowerLevel1;
++  long  TxPowerLevel2;
++  long  TxPowerLevel3;
++  long  TxPowerLevel4;
++  long  TxPowerLevel5;
++  long  TxPowerLevel6;
++  long  TxPowerLevel7;
++  long  TxPowerLevel8;
++  long  currentTxPowerLevel;
++
++  long  haveNumberSupportedPowerLevels;
++  long  haveTxPowerLevel1;
++  long  haveTxPowerLevel2;
++  long  haveTxPowerLevel3;
++  long  haveTxPowerLevel4;
++  long  haveTxPowerLevel5;
++  long  haveTxPowerLevel6;
++  long  haveTxPowerLevel7;
++  long  haveTxPowerLevel8;
++  long  haveCurrentTxPowerLevel ;
++
++} nPt, *pt = &nPt;
++
++static avList_t ptList;
++
++/****************************************************************************
++*                               dot11PhyFHSSTable                           *
++****************************************************************************/
++static struct pfTbl_data {
++
++  char  UID       [ PF_UID_LEN + 1 ];              // unique ID
++  char  ifName    [ IFNAME_LEN + 1 ];              // ifName of card
++
++  long  ifIndex;                                    // ifindex of card
++
++  long  hopTime;
++  long  currentChannelNumber;
++  long  maxDwellTime;
++  long  currentDwellTime;
++  long  currentSet;
++  long  currentPattern;
++  long  currentIndex;
++
++  long  haveHopTime;
++  long  haveCurrentChannelNumber;
++  long  haveMaxDwellTime;
++  long  haveCurrentDwellTime;
++  long  haveCurrentSet;
++  long  haveCurrentPattern;
++  long  haveCurrentIndex;
++
++} nPf, *pf = &nPf;
++
++static avList_t pfList;
++
++/****************************************************************************
++*                              dot11PhyDSSSTable                            *
++****************************************************************************/
++static struct pdTbl_data {
++
++  char  UID       [ PD_UID_LEN + 1 ];               // unique ID
++  char  ifName    [ IFNAME_LEN + 1 ];               // ifName of card
++
++  long  ifIndex;                                    // ifindex of card
++
++  long  currentChannel;
++  long  CCAModeSupported;
++  long  currentCCAMode;
++  long  EDThreshold;
++
++  long  haveCurrentChannel;
++  long  haveCCAModeSupported ;
++  long  haveCurrentCCAMode;
++  long  haveEDThreshold;
++
++} nPd, *pd = &nPd;
++
++static avList_t pdList;
++
++/****************************************************************************
++*                              dot11PhyIRTable                              *
++****************************************************************************/
++static struct piTbl_data {
++
++  char  UID       [ PI_UID_LEN + 1 ];               // unique ID
++  char  ifName    [ IFNAME_LEN + 1 ];               // ifName of card
++
++  long  ifIndex;                                    // ifindex of card
++
++  long  CCAWatchdogTimerMax;
++  long  CCAWatchdogCountMax;
++  long  CCAWatchdogTimerMin;
++  long  CCAWatchdogCountMin;
++
++  long  haveCCAWatchdogTimerMax;
++  long  haveCCAWatchdogCountMax;
++  long  haveCCAWatchdogTimerMin;
++  long  haveCCAWatchdogCountMin;
++
++} nPi, *pi = &nPi;
++
++static avList_t piList;
++
++/****************************************************************************
++*                      dot11RegDomainsSupportedTable                        *
++****************************************************************************/
++static struct rdTbl_data {
++
++  char  UID       [ RD_UID_LEN + 1 ];
++  char  ifName    [ IFNAME_LEN + 1 ];
++
++  long  ifIndex;                                    // ifindex of card
++  long  regDomainsSupportIndex;
++
++  long  regDomainsSupportValue;
++  long  haveRegDomainsSupportValue;
++
++} nRd, *rd = &nRd;
++
++static avList_t rdList;
++
++/****************************************************************************
++*                             dot11AntennasListTable                        *
++****************************************************************************/
++static struct alTbl_data {
++
++  char  UID       [ AL_UID_LEN + 1 ];
++  char  ifName    [ IFNAME_LEN + 1 ];
++
++  long  ifIndex;                                    // ifindex of card
++  long  antennaListIndex;
++
++  long  supportedTxAntenna;
++  long  supportedRxAntenna;
++  long  diversitySelectionRx ;
++
++  long  haveSupportedTxAntenna;
++  long  haveSupportedRxAntenna;
++  long  haveDiversitySelectionRx ;
++
++} nAl, *al = &nAl;
++
++static avList_t alList;
++
++/****************************************************************************
++*                    dot11SupportedDataRatesTxTable                         *
++****************************************************************************/
++static struct rtTbl_data {
++
++  char  UID       [ RT_UID_LEN + 1 ];
++  char  ifName    [ IFNAME_LEN + 1 ];
++
++  long  ifIndex;                                    // ifindex of card
++  long  supportedDataRatesTxIndex;
++
++  long  supportedDataRatesTxValue;
++  long  haveSupportedDataRatesTxValue;
++
++} nRt, *rt = &nRt;
++
++static avList_t rtList;
++
++/****************************************************************************
++*                    dot11SupportedDataRatesRxTable                         *
++****************************************************************************/
++static struct rrTbl_data {
++
++  char  UID       [ RR_UID_LEN + 1 ];
++  char  ifName    [ IFNAME_LEN + 1 ];
++
++  long  ifIndex;                                    // ifindex of card
++  long  supportedDataRatesRxIndex;
++
++  long  supportedDataRatesRxValue;
++  long  haveSupportedDataRatesRxValue;
++
++} nRr, *rr = &nRr;
++
++static avList_t rrList;
++
++/****************************************************************************
++*                       Wireless Extensions Structures                      *
++****************************************************************************/
++static long wepCurrentKey;
++static long haveWepCurrentKey;
++static struct wepTbl_data {
++
++  long len;
++  char key [ WEP_STR_LEN + 1 ];
++  long haveKey;
++
++} wep[4];
++
++/****************************************************************************
++*                                                                           *
++****************************************************************************/
++config_require(util_funcs)
++
++/* function prototypes */
++
++void   init_ieee802dot11 ( void );
++FindVarMethod var_ieee802dot11;
++FindVarMethod var_dot11StationConfigTable;
++FindVarMethod var_dot11AuthenticationAlgorithmsTable;
++FindVarMethod var_dot11WEPDefaultKeysTable;
++FindVarMethod var_dot11WEPKeyMappingsTable;
++FindVarMethod var_dot11PrivacyTable;
++FindVarMethod var_dot11OperationTable;
++FindVarMethod var_dot11CountersTable;
++FindVarMethod var_dot11GroupAddressesTable;
++FindVarMethod var_dot11ResourceInfoTable;
++FindVarMethod var_dot11PhyOperationTable;
++FindVarMethod var_dot11PhyAntennaTable;
++FindVarMethod var_dot11PhyTxPowerTable;
++FindVarMethod var_dot11PhyFHSSTable;
++FindVarMethod var_dot11PhyDSSSTable;
++FindVarMethod var_dot11PhyIRTable;
++FindVarMethod var_dot11RegDomainsSupportedTable;
++FindVarMethod var_dot11AntennasListTable;
++FindVarMethod var_dot11SupportedDataRatesTxTable;
++FindVarMethod var_dot11SupportedDataRatesRxTable;
++
++WriteMethod write_dot11StationID;
++WriteMethod write_dot11MediumOccupancyLimit;
++WriteMethod write_dot11CFPPeriod;
++WriteMethod write_dot11CFPMaxDuration;
++WriteMethod write_dot11AuthenticationResponseTimeOut;
++WriteMethod write_dot11PowerManagementMode;
++WriteMethod write_dot11DesiredSSID;
++WriteMethod write_dot11DesiredBSSType;
++WriteMethod write_dot11OperationalRateSet;
++WriteMethod write_dot11BeaconPeriod;
++WriteMethod write_dot11DTIMPeriod;
++WriteMethod write_dot11AssociationResponseTimeOut;
++WriteMethod write_dot11AuthenticationAlgorithmsEnable;
++WriteMethod write_dot11WEPDefaultKeyValue;
++WriteMethod write_dot11WEPKeyMappingAddress;
++WriteMethod write_dot11WEPKeyMappingWEPOn;
++WriteMethod write_dot11WEPKeyMappingValue;
++WriteMethod write_dot11WEPKeyMappingStatus;
++WriteMethod write_dot11PrivacyInvoked;
++WriteMethod write_dot11WEPDefaultKeyID;
++WriteMethod write_dot11WEPKeyMappingLength;
++WriteMethod write_dot11ExcludeUnencrypted;
++WriteMethod write_dot11RTSThreshold;
++WriteMethod write_dot11ShortRetryLimit;
++WriteMethod write_dot11LongRetryLimit;
++WriteMethod write_dot11FragmentationThreshold;
++WriteMethod write_dot11MaxTransmitMSDULifetime;
++WriteMethod write_dot11MaxReceiveLifetime;
++WriteMethod write_dot11Address;
++WriteMethod write_dot11GroupAddressesStatus;
++WriteMethod write_dot11CurrentRegDomain;
++WriteMethod write_dot11CurrentTxAntenna;
++WriteMethod write_dot11CurrentRxAntenna;
++WriteMethod write_dot11CurrentTxPowerLevel;
++WriteMethod write_dot11CurrentChannelNumber;
++WriteMethod write_dot11CurrentDwellTime;
++WriteMethod write_dot11CurrentSet;
++WriteMethod write_dot11CurrentPattern;
++WriteMethod write_dot11CurrentIndex;
++WriteMethod write_dot11CurrentChannel;
++WriteMethod write_dot11CurrentCCAMode;
++WriteMethod write_dot11EDThreshold;
++WriteMethod write_dot11CCAWatchdogTimerMax;
++WriteMethod write_dot11CCAWatchdogCountMax;
++WriteMethod write_dot11CCAWatchdogTimerMin;
++WriteMethod write_dot11CCAWatchdogCountMin;
++WriteMethod write_dot11SupportedTxAntenna;
++WriteMethod write_dot11SupportedRxAntenna;
++WriteMethod write_dot11DiversitySelectionRx;
++
++#endif /* _MIBGROUP_IEEE802DOT11_H */
+--- /dev/null
++++ b/agent/mibgroup/iwlib.h
+@@ -0,0 +1,502 @@
++/*
++ *	Wireless Tools
++ *
++ *		Jean II - HPLB 97->99 - HPL 99->02
++ *
++ * Common header for the Wireless Extension library...
++ *
++ * This file is released under the GPL license.
++ *     Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
++ */
++
++#ifndef IWLIB_H
++#define IWLIB_H
++
++/*#include "CHANGELOG.h"*/
++
++/***************************** INCLUDES *****************************/
++
++/* Standard headers */
++#include <sys/types.h>
++#include <sys/ioctl.h>
++#include <stdio.h>
++#include <math.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <ctype.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <netdb.h>		/* gethostbyname, getnetbyname */
++#include <net/ethernet.h>	/* struct ether_addr */
++#include <sys/time.h>		/* struct timeval */
++#include <unistd.h>
++
++/* This is our header selection. Try to hide the mess and the misery :-(
++ * Don't look, you would go blind ;-) */
++
++#ifndef LINUX_VERSION_CODE
++#include <linux/version.h>
++#endif
++
++/* Kernel headers 2.4.X + Glibc 2.2 - Mandrake 8.0, Debian 2.3, RH 7.1
++ * Kernel headers 2.2.X + Glibc 2.2 - Slackware 8.0 */
++#if defined(__GLIBC__) \
++    && __GLIBC__ == 2 \
++    && __GLIBC_MINOR__ >= 2 \
++    && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
++//#define GLIBC22_HEADERS
++#define GENERIC_HEADERS
++
++/* Kernel headers 2.4.X + Glibc 2.1 - Debian 2.2 upgraded, RH 7.0
++ * Kernel headers 2.2.X + Glibc 2.1 - Debian 2.2, RH 6.1 */
++#elif defined(__GLIBC__) \
++      && __GLIBC__ == 2 \
++      && __GLIBC_MINOR__ == 1 \
++      && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
++//#define GLIBC_HEADERS
++#define GENERIC_HEADERS
++
++/* Kernel headers 2.2.X + Glibc 2.0 - Debian 2.1 */
++#elif defined(__GLIBC__) \
++      && __GLIBC__ == 2 \
++      && __GLIBC_MINOR__ == 0 \
++      && LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,0) \
++      && LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
++#define GLIBC_HEADERS
++#define KLUDGE_HEADERS
++
++/* Note : is it really worth supporting kernel 2.0.X, knowing that
++ * we require WE v9, which is only available in 2.2.X and higher ?
++ * I guess one could use 2.0.x with an upgraded wireless.h... */
++
++/* Kernel headers 2.0.X + Glibc 2.0 - Debian 2.0, RH 5 */
++#elif defined(__GLIBC__) \
++      && __GLIBC__ == 2 \
++      && __GLIBC_MINOR__ == 0 \
++      && LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) \
++      && LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,0)
++#define GLIBC_HEADERS
++
++/* Kernel headers 2.0.X + libc5 - old systems */
++#elif defined(_LINUX_C_LIB_VERSION_MAJOR) \
++      && _LINUX_C_LIB_VERSION_MAJOR == 5 \
++      && LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,0) \
++      && LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
++#define LIBC5_HEADERS
++
++/* Unsupported combination */
++#else
++#error "Your kernel/libc combination is not supported"
++#endif
++
++#ifdef GENERIC_HEADERS 
++/* Proposed by Dr. Michael Rietz <rietz@mail.amps.de>, 27.3.2 */
++/* If this works for all, it might be more stable on the long term - Jean II */
++#include <net/if_arp.h>		/* For ARPHRD_ETHER */
++#include <sys/socket.h>		/* For AF_INET & struct sockaddr */
++#include <netinet/in.h>         /* For struct sockaddr_in */
++#include <netinet/if_ether.h>
++#endif /* GENERIC_HEADERS */    
++
++#ifdef GLIBC22_HEADERS 
++/* Added by Ross G. Miller <Ross_Miller@baylor.edu>, 3/28/01 */
++#include <linux/if_arp.h> 	/* For ARPHRD_ETHER */
++#include <linux/socket.h>	/* For AF_INET & struct sockaddr */
++#include <sys/socket.h>
++#endif /* GLIBC22_HEADERS */    
++
++#ifdef KLUDGE_HEADERS
++#include <socketbits.h>
++#endif	/* KLUDGE_HEADERS */
++
++#ifdef GLIBC_HEADERS
++#include <linux/if_arp.h>	/* For ARPHRD_ETHER */
++#include <linux/socket.h>	/* For AF_INET & struct sockaddr */
++#include <linux/in.h>		/* For struct sockaddr_in */
++#endif	/* KLUDGE_HEADERS || GLIBC_HEADERS */
++
++#ifdef LIBC5_HEADERS
++#include <sys/socket.h>		/* For AF_INET & struct sockaddr & socket() */
++#include <linux/if_arp.h>	/* For ARPHRD_ETHER */
++#include <linux/in.h>		/* For struct sockaddr_in */
++#endif	/* LIBC5_HEADERS */
++
++/* Those 3 headers were previously included in wireless.h */
++#include <linux/types.h>		/* for "caddr_t" et al		*/
++#include <linux/socket.h>		/* for "struct sockaddr" et al	*/
++#include <linux/if.h>			/* for IFNAMSIZ and co... */
++
++#ifdef WEXT_HEADER
++/* Private copy of Wireless extensions */
++#include WEXT_HEADER
++#else	/* !WEXT_HEADER */
++/* System wide Wireless extensions */
++#include <linux/wireless.h>
++#endif	/* !WEXT_HEADER */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/****************************** DEBUG ******************************/
++
++
++/************************ CONSTANTS & MACROS ************************/
++
++/* Paths */
++#define PROC_NET_WIRELESS	"/proc/net/wireless"
++#define PROC_NET_DEV		"/proc/net/dev"
++
++/* Some useful constants */
++#define KILO	1e3
++#define MEGA	1e6
++#define GIGA	1e9
++/* For doing log10/exp10 without libm */
++#define LOG10_MAGIC	1.25892541179
++
++/* Backward compatibility for Wireless Extension 9 */
++#ifndef IW_POWER_MODIFIER
++#define IW_POWER_MODIFIER	0x000F	/* Modify a parameter */
++#define IW_POWER_MIN		0x0001	/* Value is a minimum  */
++#define IW_POWER_MAX		0x0002	/* Value is a maximum */
++#define IW_POWER_RELATIVE	0x0004	/* Value is not in seconds/ms/us */
++#endif /* IW_POWER_MODIFIER */
++
++#ifndef IW_ENCODE_NOKEY
++#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not here */
++#define IW_ENCODE_MODE		0xF000	/* Modes defined below */
++#endif /* IW_ENCODE_NOKEY */
++#ifndef IW_ENCODE_TEMP
++#define IW_ENCODE_TEMP		0x0400  /* Temporary key */
++#endif /* IW_ENCODE_TEMP */
++
++/* More backward compatibility */
++#ifndef SIOCSIWCOMMIT
++#define SIOCSIWCOMMIT	SIOCSIWNAME
++#endif /* SIOCSIWCOMMIT */
++
++/****************************** TYPES ******************************/
++
++/* Shortcuts */
++typedef struct iw_statistics	iwstats;
++typedef struct iw_range		iwrange;
++typedef struct iw_param		iwparam;
++typedef struct iw_freq		iwfreq;
++typedef struct iw_quality	iwqual;
++typedef struct iw_priv_args	iwprivargs;
++typedef struct sockaddr		sockaddr;
++
++/* Structure for storing all wireless information for each device
++ * This is pretty exhaustive... */
++typedef struct wireless_info
++{
++  char		name[IFNAMSIZ + 1];	/* Wireless/protocol name */
++  int		has_nwid;
++  iwparam	nwid;			/* Network ID */
++  int		has_freq;
++  double	freq;			/* Frequency/channel */
++  int		has_sens;
++  iwparam	sens;			/* sensitivity */
++  int		has_key;
++  unsigned char	key[IW_ENCODING_TOKEN_MAX];	/* Encoding key used */
++  int		key_size;		/* Number of bytes */
++  int		key_flags;		/* Various flags */
++  int		has_essid;
++  int		essid_on;
++  char		essid[IW_ESSID_MAX_SIZE + 1];	/* ESSID (extended network) */
++  int		has_nickname;
++  char		nickname[IW_ESSID_MAX_SIZE + 1]; /* NickName */
++  int		has_ap_addr;
++  sockaddr	ap_addr;		/* Access point address */
++  int		has_bitrate;
++  iwparam	bitrate;		/* Bit rate in bps */
++  int		has_rts;
++  iwparam	rts;			/* RTS threshold in bytes */
++  int		has_frag;
++  iwparam	frag;			/* Fragmentation threshold in bytes */
++  int		has_mode;
++  int		mode;			/* Operation mode */
++  int		has_power;
++  iwparam	power;			/* Power management parameters */
++  int		has_txpower;
++  iwparam	txpower;		/* Transmit Power in dBm */
++  int		has_retry;
++  iwparam	retry;			/* Retry limit or lifetime */
++
++  /* Stats */
++  iwstats	stats;
++  int		has_stats;
++  iwrange	range;
++  int		has_range;
++} wireless_info;
++
++/* Structure for storing all wireless information for each device
++ * This is a cut down version of the one above, containing only
++ * the things *truly* needed to configure a card.
++ * Don't add other junk, I'll remove it... */
++typedef struct wireless_config
++{
++  char		name[IFNAMSIZ + 1];	/* Wireless/protocol name */
++  int		has_nwid;
++  iwparam	nwid;			/* Network ID */
++  int		has_freq;
++  double	freq;			/* Frequency/channel */
++  int		has_key;
++  unsigned char	key[IW_ENCODING_TOKEN_MAX];	/* Encoding key used */
++  int		key_size;		/* Number of bytes */
++  int		key_flags;		/* Various flags */
++  int		has_essid;
++  int		essid_on;
++  char		essid[IW_ESSID_MAX_SIZE + 1];	/* ESSID (extended network) */
++  int		has_mode;
++  int		mode;			/* Operation mode */
++} wireless_config;
++
++typedef struct stream_descr
++{
++  char *	end;		/* End of the stream */
++  char *	current;	/* Current event in stream of events */
++  char *	value;		/* Current value in event */
++} stream_descr;
++
++/* Prototype for handling display of each single interface on the
++ * system - see iw_enum_devices() */
++typedef int (*iw_enum_handler)(int	skfd,
++			       char *	ifname,
++			       char *	args[],
++			       int	count);
++
++/**************************** PROTOTYPES ****************************/
++/*
++ * All the functions in iwcommon.c
++ */
++
++/* ---------------------- SOCKET SUBROUTINES -----------------------*/
++int
++	iw_sockets_open(void);
++void
++	iw_enum_devices(int		skfd,
++			iw_enum_handler fn,
++			char *		args[],
++			int		count);
++/* --------------------- WIRELESS SUBROUTINES ----------------------*/
++int
++	iw_get_range_info(int		skfd,
++			  char *	ifname,
++			  iwrange *	range);
++int
++	iw_print_version_info(char *	toolname);
++int
++	iw_get_priv_info(int		skfd,
++			 char *		ifname,
++			 iwprivargs *	priv,
++			 int		maxpriv);
++int
++	iw_get_basic_config(int			skfd,
++			    char *		ifname,
++			    wireless_config *	info);
++int
++	iw_set_basic_config(int			skfd,
++			    char *		ifname,
++			    wireless_config *	info);
++/* --------------------- PROTOCOL SUBROUTINES --------------------- */
++int
++	iw_protocol_compare(char *	protocol1,
++			    char *	protocol2);
++/* -------------------- FREQUENCY SUBROUTINES --------------------- */
++void
++	iw_float2freq(double	in,
++		   iwfreq *	out);
++double
++	iw_freq2float(iwfreq *	in);
++void
++	iw_print_freq(char *	buffer,
++		      double	freq);
++int
++	iw_freq_to_channel(double		freq,
++			   struct iw_range *	range);
++void
++	iw_print_bitrate(char *	buffer,
++			 int	bitrate);
++/* ---------------------- POWER SUBROUTINES ----------------------- */
++int
++	iw_dbm2mwatt(int	in);
++int
++	iw_mwatt2dbm(int	in);
++/* -------------------- STATISTICS SUBROUTINES -------------------- */
++int
++	iw_get_stats(int	skfd,
++		     char *	ifname,
++		     iwstats *	stats);
++void
++	iw_print_stats(char *		buffer,
++		       iwqual *		qual,
++		       iwrange *	range,
++		       int		has_range);
++/* --------------------- ENCODING SUBROUTINES --------------------- */
++void
++	iw_print_key(char *		buffer,
++		     unsigned char *	key,
++		     int		key_size,
++		     int		key_flags);
++int
++	iw_in_key(char *		input,
++		  unsigned char *	key);
++int
++	iw_in_key_full(int		skfd,
++		       char *		ifname,
++		       char *		input,
++		       unsigned char *	key,
++		       __u16 *		flags);
++/* ----------------- POWER MANAGEMENT SUBROUTINES ----------------- */
++void
++	iw_print_pm_value(char *	buffer,
++			  int		value,
++			  int		flags);
++void
++	iw_print_pm_mode(char *		buffer,
++			 int		flags);
++/* --------------- RETRY LIMIT/LIFETIME SUBROUTINES --------------- */
++#if WIRELESS_EXT > 10
++void
++	iw_print_retry_value(char *	buffer,
++			     int	value,
++			     int	flags);
++#endif
++/* ----------------------- TIME SUBROUTINES ----------------------- */
++void
++	iw_print_timeval(char *			buffer,
++			 const struct timeval *	time);
++/* --------------------- ADDRESS SUBROUTINES ---------------------- */
++int
++	iw_check_mac_addr_type(int	skfd,
++			       char *	ifname);
++int
++	iw_check_if_addr_type(int	skfd,
++			      char *	ifname);
++#if 0
++int
++	iw_check_addr_type(int		skfd,
++			   char *	ifname);
++#endif
++void
++	iw_ether_ntop(const struct ether_addr* eth, char* buf);
++char*
++	iw_ether_ntoa(const struct ether_addr* eth);
++int
++	iw_ether_aton(const char* bufp, struct ether_addr* eth);
++int
++	iw_in_inet(char *bufp, struct sockaddr *sap);
++int
++	iw_in_addr(int			skfd,
++		   char *		ifname,
++		   char *		bufp,
++		   struct sockaddr *	sap);
++/* ----------------------- MISC SUBROUTINES ------------------------ */
++int
++	iw_get_priv_size(int		args);
++
++#if WIRELESS_EXT > 13
++/* ---------------------- EVENT SUBROUTINES ---------------------- */
++void
++	iw_init_event_stream(struct stream_descr *	stream,
++			     char *			data,
++			     int			len);
++int
++	iw_extract_event_stream(struct stream_descr *	stream,
++				struct iw_event *	iwe);
++#endif /* WIRELESS_EXT > 13 */
++
++/**************************** VARIABLES ****************************/
++
++extern const char * const	iw_operation_mode[];
++#define IW_NUM_OPER_MODE	7
++
++/************************* INLINE FUNTIONS *************************/
++/*
++ * Functions that are so simple that it's more efficient inlining them
++ */
++
++/*
++ * Note : I've defined wrapper for the ioctl request so that
++ * it will be easier to migrate to other kernel API if needed
++ */
++
++/*------------------------------------------------------------------*/
++/*
++ * Wrapper to push some Wireless Parameter in the driver
++ */
++static inline int
++iw_set_ext(int			skfd,		/* Socket to the kernel */
++	   char *		ifname,		/* Device name */
++	   int			request,	/* WE ID */
++	   struct iwreq *	pwrq)		/* Fixed part of the request */
++{
++  /* Set device name */
++  strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
++  /* Do the request */
++  return(ioctl(skfd, request, pwrq));
++}
++
++/*------------------------------------------------------------------*/
++/*
++ * Wrapper to extract some Wireless Parameter out of the driver
++ */
++static inline int
++iw_get_ext(int			skfd,		/* Socket to the kernel */
++	   char *		ifname,		/* Device name */
++	   int			request,	/* WE ID */
++	   struct iwreq *	pwrq)		/* Fixed part of the request */
++{
++  /* Set device name */
++  strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
++  /* Do the request */
++  return(ioctl(skfd, request, pwrq));
++}
++
++/*------------------------------------------------------------------*/
++/* Backwards compatibility
++ * Actually, those form are much easier to use when dealing with
++ * struct sockaddr... */
++static inline char*
++iw_pr_ether(char* bufp, const unsigned char* addr)
++{
++  iw_ether_ntop((const struct ether_addr *) addr, bufp);
++  return bufp;
++}
++/* Backwards compatibility */
++static inline int
++iw_in_ether(const char *bufp, struct sockaddr *sap)
++{
++  sap->sa_family = ARPHRD_ETHER;
++  return iw_ether_aton(bufp, (struct ether_addr *) sap->sa_data) ? 0 : -1;
++}
++
++/*------------------------------------------------------------------*/
++/*
++ * Create an Ethernet broadcast address
++ */
++static inline void
++iw_broad_ether(struct sockaddr *sap)
++{
++  sap->sa_family = ARPHRD_ETHER;
++  memset((char *) sap->sa_data, 0xFF, ETH_ALEN);
++}
++
++/*------------------------------------------------------------------*/
++/*
++ * Create an Ethernet NULL address
++ */
++static inline void
++iw_null_ether(struct sockaddr *sap)
++{
++  sap->sa_family = ARPHRD_ETHER;
++  memset((char *) sap->sa_data, 0x00, ETH_ALEN);
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* IWLIB_H */
diff --git a/package/network/utils/net-snmp/patches/900-musl-compat.patch b/package/network/utils/net-snmp/patches/900-musl-compat.patch
new file mode 100644
index 0000000..fa9a01e
--- /dev/null
+++ b/package/network/utils/net-snmp/patches/900-musl-compat.patch
@@ -0,0 +1,14 @@
+--- a/agent/mibgroup/iwlib.h
++++ b/agent/mibgroup/iwlib.h
+@@ -85,6 +85,11 @@
+       && LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+ #define LIBC5_HEADERS
+ 
++/* Musl */
++#elif !defined(__GLIBC__) && !defined(__UCLIBC__) \
++      && LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)
++#define GENERIC_HEADERS
++
+ /* Unsupported combination */
+ #else
+ #error "Your kernel/libc combination is not supported"
diff --git a/package/network/utils/net-snmp/patches/910-signal.patch b/package/network/utils/net-snmp/patches/910-signal.patch
new file mode 100644
index 0000000..45cd1fa
--- /dev/null
+++ b/package/network/utils/net-snmp/patches/910-signal.patch
@@ -0,0 +1,143 @@
+From 1ee70571e0cae37f155f59d4382bc7109138cf09 Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bvanassche@acm.org>
+Date: Sat, 15 Aug 2020 17:29:25 -0700
+Subject: [PATCH] apps/snmpnetstat: Stop using obsolete signal functions
+
+This was reported by Rosen Penev. See also
+https://github.com/net-snmp/net-snmp/pull/162.
+---
+ apps/snmpnetstat/if.c | 111 +++++++++++-------------------------------
+ 1 file changed, 28 insertions(+), 83 deletions(-)
+ mode change 100644 => 100755 apps/snmpnetstat/if.c
+
+--- a/apps/snmpnetstat/if.c
++++ b/apps/snmpnetstat/if.c
+@@ -64,8 +64,6 @@ static char *rcsid = "$OpenBSD: if.c,v 1
+ #define	NO	0
+ 
+ static void sidewaysintpr(u_int);
+-static void timerSet(int interval_seconds);
+-static void timerPause(void);
+ 
+     struct _if_info {
+         char            name[128];
+@@ -92,6 +90,34 @@ static void timerPause(void);
+     };
+ 
+ 
++static struct timeval deadline;
++
++static void
++timerSet(int interval_seconds)
++{
++    const struct timeval interval = { interval_seconds, 0 };
++
++    netsnmp_get_monotonic_clock(&deadline);
++    NETSNMP_TIMERADD(&deadline, &interval, &deadline);
++}
++
++static void
++timerPause(void)
++{
++    struct timeval now, delta;
++
++    netsnmp_get_monotonic_clock(&now);
++    NETSNMP_TIMERSUB(&deadline, &now, &delta);
++    if (delta.tv_sec < 0)
++        return;
++#ifdef WIN32
++    Sleep(delta.tv_sec * 1000 + delta.tv_usec / 1000);
++#else
++    if (select(0, NULL, NULL, NULL, &delta) < 0)
++        snmp_perror("select");
++#endif
++}
++
+ /*
+  * Retrieve the interface addressing information
+  * XXX - This could also be extended to handle non-IP interfaces
+@@ -845,84 +871,3 @@ loop:
+     	goto loop;
+     /*NOTREACHED*/
+ }
+-
+-
+-/*
+- * timerSet sets or resets the timer to fire in "interval" seconds.
+- * timerPause waits only if the timer has not fired.
+- * timing precision is not considered important.
+- */
+-
+-#if (defined(WIN32) || defined(cygwin))
+-static int      sav_int;
+-static time_t   timezup;
+-static void
+-timerSet(int interval_seconds)
+-{
+-    sav_int = interval_seconds;
+-    timezup = time(0) + interval_seconds;
+-}
+-
+-/*
+- * you can do better than this ! 
+- */
+-static void
+-timerPause(void)
+-{
+-    time_t          now;
+-    while (time(&now) < timezup)
+-#ifdef WIN32
+-        Sleep(400);
+-#else
+-    {
+-        struct timeval  tx;
+-        tx.tv_sec = 0;
+-        tx.tv_usec = 400 * 1000;        /* 400 milliseconds */
+-        select(0, 0, 0, 0, &tx);
+-    }
+-#endif
+-}
+-
+-#else
+-
+-/*
+- * Called if an interval expires before sidewaysintpr has completed a loop.
+- * Sets a flag to not wait for the alarm.
+- */
+-RETSIGTYPE
+-catchalarm(int sig)
+-{
+-    signalled = YES;
+-}
+-
+-static void
+-timerSet(int interval_seconds)
+-{
+-#ifdef HAVE_SIGSET
+-    (void) sigset(SIGALRM, catchalarm);
+-#else
+-    (void) signal(SIGALRM, catchalarm);
+-#endif
+-    signalled = NO;
+-    (void) alarm(interval_seconds);
+-}
+-
+-static void
+-timerPause(void)
+-{
+-#ifdef HAVE_SIGHOLD
+-    sighold(SIGALRM);
+-    if (!signalled) {
+-        sigpause(SIGALRM);
+-    }
+-#else
+-    int             oldmask;
+-    oldmask = sigblock(sigmask(SIGALRM));
+-    if (!signalled) {
+-        sigpause(0);
+-    }
+-    sigsetmask(oldmask);
+-#endif
+-}
+-
+-#endif                          /* !WIN32 && !cygwin */
diff --git a/package/network/utils/nftables/Makefile b/package/network/utils/nftables/Makefile
new file mode 100644
index 0000000..06b3fcf
--- /dev/null
+++ b/package/network/utils/nftables/Makefile
@@ -0,0 +1,85 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=nftables
+PKG_VERSION:=1.1.1
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://netfilter.org/projects/$(PKG_NAME)/files
+PKG_HASH:=6358830f3a64f31e39b0ad421d7dadcd240b72343ded48d8ef13b8faf204865a
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=COPYING
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+
+PKG_BUILD_FLAGS:=lto
+
+include $(INCLUDE_DIR)/package.mk
+
+DISABLE_NLS:=
+
+CONFIGURE_ARGS += \
+        --disable-debug \
+        --disable-man-doc \
+        --with-mini-gmp \
+        --without-cli \
+        --disable-python
+
+define Package/nftables/Default
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=Firewall
+  TITLE:=nftables userspace utility
+  DEPENDS:=+kmod-nft-core +libnftnl
+  URL:=http://netfilter.org/projects/nftables/
+  PROVIDES:=nftables
+endef
+
+define Package/nftables-nojson
+  $(Package/nftables/Default)
+  TITLE+= no JSON support
+  VARIANT:=nojson
+  DEFAULT_VARIANT:=1
+  CONFLICTS:=nftables-json
+endef
+
+define Package/nftables-json
+  $(Package/nftables/Default)
+  TITLE+= with JSON support
+  VARIANT:=json
+  DEPENDS+=+jansson
+endef
+
+ifeq ($(BUILD_VARIANT),json)
+  CONFIGURE_ARGS += --with-json
+endif
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(1)/usr/lib $(1)/usr/include
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/nftables $(1)/usr/include/
+	$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libnftables.pc \
+		$(1)/usr/lib/pkgconfig/
+endef
+
+define Package/nftables/install/Default
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(CP) $(PKG_INSTALL_DIR)/usr/sbin/nft $(1)/usr/sbin/
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/
+endef
+
+Package/nftables-nojson/install = $(Package/nftables/install/Default)
+Package/nftables-json/install = $(Package/nftables/install/Default)
+
+$(eval $(call BuildPackage,nftables-nojson))
+$(eval $(call BuildPackage,nftables-json))
diff --git a/package/network/utils/resolveip/Makefile b/package/network/utils/resolveip/Makefile
new file mode 100644
index 0000000..ab5d4ea
--- /dev/null
+++ b/package/network/utils/resolveip/Makefile
@@ -0,0 +1,41 @@
+#
+# 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 <jo@mein.io>
+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/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..f7a918d
--- /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 <jo@mein.io> 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..5adc25e
--- /dev/null
+++ b/package/network/utils/rssileds/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2011-2012 Daniel Golle <dgolle@allnet.de>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=rssileds
+PKG_RELEASE:=4
+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 +libnl-tiny +libubox +libuci
+  MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+endef
+
+define Package/rssileds/description
+  A small process written in C to update the signal-strength indicator LEDs
+endef
+
+define Build/Configure
+endef
+
+TARGET_LDFLAGS += -liwinfo -luci -lubox -lnl-tiny
+
+define Build/Compile
+	$(TARGET_CC) $(TARGET_CFLAGS) $(TARGET_CPPFLAGS) -Wall \
+		-o $(PKG_BUILD_DIR)/rssileds $(PKG_BUILD_DIR)/rssileds.c $(TARGET_LDFLAGS)
+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/
+	$(INSTALL_DIR) $(1)/usr/libexec/led-trigger
+	$(INSTALL_BIN) ./files/rssi $(1)/usr/libexec/led-trigger/
+endef
+
+$(eval $(call BuildPackage,rssileds))
diff --git a/package/network/utils/rssileds/files/rssi b/package/network/utils/rssileds/files/rssi
new file mode 100644
index 0000000..0c06733
--- /dev/null
+++ b/package/network/utils/rssileds/files/rssi
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+logger -t led-trigger "LED trigger rssi is handled by /etc/init.d/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..4c9b549
--- /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=89
+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..bb42888
--- /dev/null
+++ b/package/network/utils/tcpdump/Makefile
@@ -0,0 +1,66 @@
+#
+# 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.99.5
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://www.tcpdump.org/release/
+PKG_HASH:=8c75856e00addeeadf70dad67c9ff3dd368536b2b8563abf6854d7c764cd3adb
+
+PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
+PKG_LICENSE:=BSD-3-Clause
+PKG_CPE_ID:=cpe:/a:tcpdump:tcpdump
+
+PKG_INSTALL:=1
+PKG_BUILD_FLAGS:=gc-sections
+PKG_BUILD_PARALLEL:=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-cap-ng \
+	--without-crypto \
+	$(call autoconf_bool,CONFIG_IPV6,ipv6)
+
+ifeq ($(BUILD_VARIANT),mini)
+  TARGET_CFLAGS += -DTCPDUMP_MINI
+  CONFIGURE_ARGS += --disable-smb
+  MAKE_FLAGS += TCPDUMP_MINI=1
+endif
+
+define Package/tcpdump/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/tcpdump $(1)/usr/bin/
+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..948e3b5
--- /dev/null
+++ b/package/network/utils/tcpdump/patches/001-remove_pcap_debug.patch
@@ -0,0 +1,100 @@
+--- a/configure
++++ b/configure
+@@ -7346,97 +7346,6 @@ esac
+ fi
+ 
+ 
+-#
+-# Check for special debugging functions
+-#
+-ac_fn_c_check_func "$LINENO" "pcap_set_parser_debug" "ac_cv_func_pcap_set_parser_debug"
+-if test "x$ac_cv_func_pcap_set_parser_debug" = xyes
+-then :
+-  printf "%s\n" "#define HAVE_PCAP_SET_PARSER_DEBUG 1" >>confdefs.h
+-
+-fi
+-
+-if test "$ac_cv_func_pcap_set_parser_debug" = "no" ; then
+-	#
+-	# OK, we don't have pcap_set_parser_debug() to set the libpcap
+-	# filter expression parser debug flag; can we directly set the
+-	# flag?
+-	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pcap_debug is defined by libpcap" >&5
+-printf %s "checking whether pcap_debug is defined by libpcap... " >&6; }
+-	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h.  */
+-
+-int
+-main (void)
+-{
+-
+-		extern int pcap_debug;
+-
+-		return pcap_debug;
+-
+-  ;
+-  return 0;
+-}
+-
+-_ACEOF
+-if ac_fn_c_try_link "$LINENO"
+-then :
+-  ac_lbl_cv_pcap_debug_defined=yes
+-else $as_nop
+-  ac_lbl_cv_pcap_debug_defined=no
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
+-    conftest$ac_exeext conftest.$ac_ext
+-	if test "$ac_lbl_cv_pcap_debug_defined" = yes ; then
+-		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+-printf "%s\n" "yes" >&6; }
+-
+-printf "%s\n" "#define HAVE_PCAP_DEBUG 1" >>confdefs.h
+-
+-	else
+-		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-		#
+-		# OK, what about "yydebug"?
+-		#
+-		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether yydebug is defined by libpcap" >&5
+-printf %s "checking whether yydebug is defined by libpcap... " >&6; }
+-		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h.  */
+-
+-int
+-main (void)
+-{
+-
+-			extern int yydebug;
+-
+-			return yydebug;
+-
+-  ;
+-  return 0;
+-}
+-
+-_ACEOF
+-if ac_fn_c_try_link "$LINENO"
+-then :
+-  ac_lbl_cv_yydebug_defined=yes
+-else $as_nop
+-  ac_lbl_cv_yydebug_defined=no
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
+-    conftest$ac_exeext conftest.$ac_ext
+-		if test "$ac_lbl_cv_yydebug_defined" = yes ; then
+-			{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+-printf "%s\n" "yes" >&6; }
+-
+-printf "%s\n" "#define HAVE_YYDEBUG 1" >>confdefs.h
+-
+-		else
+-			{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-		fi
+-	fi
+-fi
+ ac_fn_c_check_func "$LINENO" "pcap_set_optimizer_debug" "ac_cv_func_pcap_set_optimizer_debug"
+ if test "x$ac_cv_func_pcap_set_optimizer_debug" = xyes
+ then :
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..eeaa17c
--- /dev/null
+++ b/package/network/utils/tcpdump/patches/100-tcpdump_mini.patch
@@ -0,0 +1,861 @@
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -73,6 +73,86 @@ DEPENDENCY_CFLAG = @DEPENDENCY_CFLAG@
+ 
+ CSRC =	fptype.c tcpdump.c
+ 
++ifdef TCPDUMP_MINI
++
++LIBNETDISSECT_SRC=\
++	netdissect.c \
++	netdissect-alloc.c \
++	addrtoname.c \
++	addrtostr.c \
++	af.c \
++	ascii_strcasecmp.c \
++	checksum.c \
++	cpack.c \
++	gmpls.c \
++	in_cksum.c \
++	ipproto.c \
++	l2vpn.c \
++	machdep.c \
++	ntp.c \
++	nlpid.c \
++	oui.c \
++	parsenfsfh.c \
++	print.c \
++	print-802_11.c \
++	print-aodv.c \
++	print-arista.c \
++	print-arp.c \
++	print-ascii.c \
++	print-bootp.c \
++	print-dhcp6.c \
++	print-domain.c \
++	print-eap.c \
++	print-ether.c \
++	print-ftp.c \
++	print-gre.c \
++	print-http.c \
++	print-icmp.c \
++	print-icmp6.c \
++	print-igmp.c \
++	print-ip-demux.c \
++	print-ip.c \
++	print-ip6.c \
++	print-ip6opts.c \
++	print-ipnet.c \
++	print-l2tp.c \
++	print-llc.c \
++	print-lldp.c \
++	print-loopback.c \
++	print-macsec.c \
++	print-nfs.c \
++	print-ntp.c \
++	print-null.c \
++	print-olsr.c \
++	print-ospf.c \
++	print-ospf6.c \
++	print-ppp.c \
++	print-pppoe.c \
++	print-pptp.c \
++	print-radius.c \
++	print-raw.c \
++	print-rsvp.c \
++	print-rt6.c \
++	print-rtsp.c \
++	print-sip.c \
++	print-sll.c \
++	print-smtp.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 \
++	print-unsupported.c \
++	print-whois.c \
++	signature.c \
++	strtoaddr.c \
++	util-print.c
++
++else
++
+ LIBNETDISSECT_SRC=\
+ 	addrtoname.c \
+ 	addrtostr.c \
+@@ -254,6 +334,8 @@ LIBNETDISSECT_SRC=\
+ 	strtoaddr.c \
+ 	util-print.c
+ 
++endif
++
+ LOCALSRC = @LOCALSRC@
+ LIBOBJS = @LIBOBJS@
+ 
+--- a/addrtoname.c
++++ b/addrtoname.c
+@@ -677,8 +677,10 @@ linkaddr_string(netdissect_options *ndo,
+ 	if (type == LINKADDR_ETHER && len == MAC_ADDR_LEN)
+ 		return (etheraddr_string(ndo, ep));
+ 
++#ifndef TCPDUMP_MINI
+ 	if (type == LINKADDR_FRELAY)
+ 		return (q922_string(ndo, ep, len));
++#endif
+ 
+ 	tp = lookup_bytestring(ndo, ep, len);
+ 	if (tp->bs_name)
+@@ -1257,6 +1259,7 @@ init_addrtoname(netdissect_options *ndo,
+ 	init_ipxsaparray(ndo);
+ }
+ 
++#ifndef TCPDUMP_MINI
+ const char *
+ dnaddr_string(netdissect_options *ndo, u_short dnaddr)
+ {
+@@ -1273,6 +1276,7 @@ dnaddr_string(netdissect_options *ndo, u
+ 
+ 	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
+@@ -543,6 +543,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);
+@@ -573,6 +574,7 @@ ethertype_print(netdissect_options *ndo,
+ 		ND_TCHECK_LEN(p, 1);
+ 		isoclns_print(ndo, p + 1, length - 1);
+ 		return(1);
++#endif
+ 
+ 	case ETHERTYPE_PPPOED:
+ 	case ETHERTYPE_PPPOES:
+@@ -585,9 +587,11 @@ ethertype_print(netdissect_options *ndo,
+ 		eapol_print(ndo, p);
+ 		return (1);
+ 
++#ifndef TCPDUMP_MINI
+ 	case ETHERTYPE_REALTEK:
+ 		rtl_print(ndo, p, length, src, dst);
+ 		return (1);
++#endif
+ 
+ 	case ETHERTYPE_PPP:
+ 		if (length) {
+@@ -596,6 +600,7 @@ ethertype_print(netdissect_options *ndo,
+ 		}
+ 		return (1);
+ 
++#ifndef TCPDUMP_MINI
+ 	case ETHERTYPE_MPCP:
+ 		mpcp_print(ndo, p, length);
+ 		return (1);
+@@ -608,19 +613,23 @@ 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);
+ 
++#ifndef TCPDUMP_MINI
+ 	case ETHERTYPE_NSH:
+ 		nsh_print(ndo, p, length);
+ 		return (1);
++#endif
+ 
+ 	case ETHERTYPE_LOOPBACK:
+ 		loopback_print(ndo, p, length);
+ 		return (1);
+ 
++#ifndef TCPDUMP_MINI
+ 	case ETHERTYPE_MPLS:
+ 	case ETHERTYPE_MPLS_MULTI:
+ 		mpls_print(ndo, p, length);
+@@ -650,6 +659,7 @@ ethertype_print(netdissect_options *ndo,
+ 	case ETHERTYPE_PTP:
+ 		ptp_print(ndo, p, length);
+ 		return (1);
++#endif
+ 
+ 	case ETHERTYPE_LAT:
+ 	case ETHERTYPE_SCA:
+--- a/print-gre.c
++++ b/print-gre.c
+@@ -205,6 +205,7 @@ gre_print_0(netdissect_options *ndo, con
+ 	case ETHERTYPE_IPV6:
+ 		ip6_print(ndo, bp, len);
+ 		break;
++#ifndef TCPDUMP_MINI
+ 	case ETHERTYPE_MPLS:
+ 		mpls_print(ndo, bp, len);
+ 		break;
+@@ -217,6 +218,7 @@ gre_print_0(netdissect_options *ndo, con
+ 	case ETHERTYPE_GRE_ISO:
+ 		isoclns_print(ndo, bp, len);
+ 		break;
++#endif
+ 	case ETHERTYPE_TEB:
+ 		ether_print(ndo, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL);
+ 		break;
+--- a/print-icmp6.c
++++ b/print-icmp6.c
+@@ -1369,7 +1369,7 @@ get_upperlayer(netdissect_options *ndo,
+ 			nh = GET_U_1(fragh->ip6f_nxt);
+ 			hlen = sizeof(struct ip6_frag);
+ 			break;
+-
++#ifndef TCPDUMP_MINI
+ 		case IPPROTO_AH:
+ 			ah = (const struct ah *)bp;
+ 			if (!ND_TTEST_1(ah->ah_len))
+@@ -1377,7 +1377,7 @@ get_upperlayer(netdissect_options *ndo,
+ 			nh = GET_U_1(ah->ah_nxt);
+ 			hlen = (GET_U_1(ah->ah_len) + 2) << 2;
+ 			break;
+-
++#endif
+ 		default:	/* unknown or undecodable header */
+ 			*prot = nh; /* meaningless, but set here anyway */
+ 			return(NULL);
+--- a/print-igmp.c
++++ b/print-igmp.c
+@@ -267,6 +267,7 @@ igmp_print(netdissect_options *ndo,
+     case 0x17:
+         ND_PRINT("igmp leave %s", GET_IPADDR_STRING(bp + 4));
+         break;
++#ifndef TCPDUMP_MINI
+     case 0x13:
+         ND_PRINT("igmp dvmrp");
+         if (len < 8)
+@@ -278,6 +279,7 @@ igmp_print(netdissect_options *ndo,
+         ND_PRINT("igmp pimv1");
+         pimv1_print(ndo, bp, len);
+         break;
++#endif
+     case 0x1e:
+         print_mtrace(ndo, "mresp", bp, len);
+         break;
+--- a/print-ip-demux.c
++++ b/print-ip-demux.c
+@@ -46,6 +46,7 @@ ip_demux_print(netdissect_options *ndo,
+ again:
+ 	switch (nh) {
+ 
++#ifndef TCPDUMP_MINI
+ 	case IPPROTO_AH:
+ 		if (!ND_TTEST_1(bp)) {
+ 			ndo->ndo_protocol = "ah";
+@@ -83,7 +84,9 @@ again:
+ 		 */
+ 		break;
+ 	}
++#endif
+ 
++#ifndef TCPDUMP_MINI
+ 	case IPPROTO_SCTP:
+ 		sctp_print(ndo, bp, iph, length);
+ 		break;
+@@ -91,7 +94,7 @@ again:
+ 	case IPPROTO_DCCP:
+ 		dccp_print(ndo, bp, iph, length);
+ 		break;
+-
++#endif
+ 	case IPPROTO_TCP:
+ 		tcp_print(ndo, bp, length, iph, fragmented);
+ 		break;
+@@ -120,6 +123,7 @@ again:
+ 		}
+ 		break;
+ 
++#ifndef TCPDUMP_MINI
+ 	case IPPROTO_PIGP:
+ 		/*
+ 		 * XXX - the current IANA protocol number assignments
+@@ -140,14 +144,17 @@ again:
+ 	case IPPROTO_EIGRP:
+ 		eigrp_print(ndo, bp, length);
+ 		break;
++#endif
+ 
+ 	case IPPROTO_ND:
+ 		ND_PRINT(" nd %u", length);
+ 		break;
+ 
++#ifndef TCPDUMP_MINI
+ 	case IPPROTO_EGP:
+ 		egp_print(ndo, bp, length);
+ 		break;
++#endif
+ 
+ 	case IPPROTO_OSPF:
+ 		if (ver == 6)
+@@ -184,6 +191,7 @@ again:
+ 		gre_print(ndo, bp, length);
+ 		break;
+ 
++#ifndef TCPDUMP_MINI
+ 	case IPPROTO_MOBILE:
+ 		mobile_print(ndo, bp, length);
+ 		break;
+@@ -203,6 +211,7 @@ again:
+ 	case IPPROTO_PGM:
+ 		pgm_print(ndo, bp, length, iph);
+ 		break;
++#endif
+ 
+ 	case IPPROTO_ETHERNET:
+ 		if (ver == 6)
+--- a/print-ip6.c
++++ b/print-ip6.c
+@@ -133,10 +133,11 @@ ip6_finddst(netdissect_options *ndo, nd_
+ 			 * Only one routing header to a customer.
+ 			 */
+ 			goto done;
+-
++#ifndef TCPDUMP_MINI
+ 		case IPPROTO_AH:
+ 		case IPPROTO_ESP:
+ 		case IPPROTO_IPCOMP:
++#endif
+ 		default:
+ 			/*
+ 			 * AH and ESP are, in the RFCs that describe them,
+@@ -371,6 +372,7 @@ ip6_print(netdissect_options *ndo, const
+ 			nh = GET_U_1(cp);
+ 			break;
+ 
++#ifndef TCPDUMP_MINI
+ 		case IPPROTO_FRAGMENT:
+ 			advance = frag6_print(ndo, cp, (const u_char *)ip6);
+ 			if (advance < 0 || ndo->ndo_snapend <= cp + advance) {
+@@ -401,7 +403,7 @@ ip6_print(netdissect_options *ndo, const
+ 			nh = GET_U_1(cp);
+ 			nd_pop_packet_info(ndo);
+ 			return;
+-
++#endif
+ 		case IPPROTO_ROUTING:
+ 			ND_TCHECK_1(cp);
+ 			advance = rt6_print(ndo, cp, (const u_char *)ip6);
+--- a/print-llc.c
++++ b/print-llc.c
+@@ -205,6 +205,7 @@ llc_print(netdissect_options *ndo, const
+ 		hdrlen = 4;	/* DSAP, SSAP, 2-byte control field */
+ 	}
+ 
++#ifndef TCPDUMP_MINI
+ 	if (ssap_field == LLCSAP_GLOBAL && dsap_field == LLCSAP_GLOBAL) {
+ 		/*
+ 		 * This is an Ethernet_802.3 IPX frame; it has an
+@@ -227,6 +228,7 @@ llc_print(netdissect_options *ndo, const
+             ipx_print(ndo, p, length);
+             return (0);		/* no LLC header */
+ 	}
++#endif
+ 
+ 	dsap = dsap_field & ~LLC_IG;
+ 	ssap = ssap_field & ~LLC_GSAP;
+@@ -290,6 +292,7 @@ llc_print(netdissect_options *ndo, const
+ 		return (hdrlen);
+ 	}
+ 
++#ifndef TCPDUMP_MINI
+ 	if (ssap == LLCSAP_IPX && dsap == LLCSAP_IPX &&
+ 	    control == LLC_UI) {
+ 		/*
+@@ -303,6 +306,7 @@ llc_print(netdissect_options *ndo, const
+ 		ipx_print(ndo, p, length);
+ 		return (hdrlen);
+ 	}
++#endif
+ 
+ #ifdef ENABLE_SMB
+ 	if (ssap == LLCSAP_NETBEUI && dsap == LLCSAP_NETBEUI
+@@ -321,12 +325,13 @@ llc_print(netdissect_options *ndo, const
+ 		return (hdrlen);
+ 	}
+ #endif
++#ifndef TCPDUMP_MINI
+ 	if (ssap == LLCSAP_ISONS && dsap == LLCSAP_ISONS
+ 	    && control == LLC_UI) {
+ 		isoclns_print(ndo, p, length);
+ 		return (hdrlen);
+ 	}
+-
++#endif
+ 	if (!ndo->ndo_eflag) {
+ 		if (ssap == dsap) {
+ 			if (src == NULL || dst == NULL)
+@@ -482,6 +487,7 @@ snap_print(netdissect_options *ndo, cons
+ 
+ 	case OUI_CISCO:
+                 switch (et) {
++#ifndef TCPDUMP_MINI
+                 case PID_CISCO_CDP:
+                         cdp_print(ndo, p, length);
+                         return (1);
+@@ -494,6 +500,7 @@ snap_print(netdissect_options *ndo, cons
+                 case PID_CISCO_VTP:
+                         vtp_print(ndo, p, length);
+                         return (1);
++#endif
+                 case PID_CISCO_PVST:
+                 case PID_CISCO_VLANBRIDGE:
+                         stp_print(ndo, p, length);
+@@ -506,6 +513,7 @@ snap_print(netdissect_options *ndo, cons
+ 	case OUI_RFC2684:
+ 		switch (et) {
+ 
++#ifndef TCPDUMP_MINI
+ 		case PID_RFC2684_ETH_FCS:
+ 		case PID_RFC2684_ETH_NOFCS:
+ 			/*
+@@ -567,6 +575,7 @@ snap_print(netdissect_options *ndo, cons
+ 			 */
+ 			fddi_print(ndo, p, length, caplen);
+ 			return (1);
++#endif
+ 
+ 		case PID_RFC2684_BPDU:
+ 			stp_print(ndo, p, length);
+--- a/print-null.c
++++ b/print-null.c
+@@ -114,6 +114,7 @@ null_if_print(netdissect_options *ndo, c
+ 		ip6_print(ndo, p, length);
+ 		break;
+ 
++#ifndef TCPDUMP_MINI
+ 	case BSD_AFNUM_ISO:
+ 		isoclns_print(ndo, p, length);
+ 		break;
+@@ -125,6 +126,7 @@ null_if_print(netdissect_options *ndo, c
+ 	case BSD_AFNUM_IPX:
+ 		ipx_print(ndo, p, length);
+ 		break;
++#endif
+ 
+ 	default:
+ 		/* unknown AF_ value */
+--- a/print-ppp.c
++++ b/print-ppp.c
+@@ -1354,6 +1354,7 @@ trunc:
+  * The length argument is the on-the-wire length, not the captured
+  * length; we can only un-escape the captured part.
+  */
++#ifndef TCPDUMP_MINI
+ static void
+ ppp_hdlc(netdissect_options *ndo,
+          const u_char *p, u_int length)
+@@ -1451,17 +1452,19 @@ trunc:
+ 	nd_pop_packet_info(ndo);
+ 	nd_print_trunc(ndo);
+ }
+-
++#endif
+ 
+ /* PPP */
+ static void
+ handle_ppp(netdissect_options *ndo,
+            u_int proto, const u_char *p, u_int length)
+ {
++#ifndef TCPDUMP_MINI
+ 	if ((proto & 0xff00) == 0x7e00) { /* is this an escape code ? */
+ 		ppp_hdlc(ndo, p - 1, length);
+ 		return;
+ 	}
++#endif
+ 
+ 	switch (proto) {
+ 	case PPP_LCP: /* fall through */
+@@ -1494,6 +1497,7 @@ handle_ppp(netdissect_options *ndo,
+ 	case PPP_IPV6:
+ 		ip6_print(ndo, p, length);
+ 		break;
++#ifndef TCPDUMP_MINI
+ 	case ETHERTYPE_IPX:	/*XXX*/
+ 	case PPP_IPX:
+ 		ipx_print(ndo, p, length);
+@@ -1505,6 +1509,7 @@ handle_ppp(netdissect_options *ndo,
+ 	case PPP_MPLS_MCAST:
+ 		mpls_print(ndo, p, length);
+ 		break;
++#endif
+ 	case PPP_COMP:
+ 		ND_PRINT("compressed PPP data");
+ 		break;
+@@ -1652,6 +1657,7 @@ ppp_if_print(netdissect_options *ndo,
+ 	ppp_print(ndo, p, length);
+ }
+ 
++#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,
+@@ -1895,3 +1901,4 @@ printx:
+ #endif /* __bsdi__ */
+ 	ndo->ndo_ll_hdr_len += hdrlength;
+ }
++#endif
+--- a/print-sll.c
++++ b/print-sll.c
+@@ -463,12 +463,14 @@ recurse:
+ 		 */
+ 		switch (ether_type) {
+ 
++#ifndef TCPDUMP_MINI
+ 		case LINUX_SLL_P_802_3:
+ 			/*
+ 			 * Ethernet_802.3 IPX frame.
+ 			 */
+ 			ipx_print(ndo, p, length);
+ 			break;
++#endif
+ 
+ 		case LINUX_SLL_P_802_2:
+ 			/*
+--- a/print-tcp.c
++++ b/print-tcp.c
+@@ -612,6 +612,7 @@ tcp_print(netdissect_options *ndo,
+                                 ND_PRINT(" %u", utoval);
+                                 break;
+ 
++#ifndef TCPDUMP_MINI
+                         case TCPOPT_MPTCP:
+                             {
+                                 const u_char *snapend_save;
+@@ -635,7 +636,7 @@ tcp_print(netdissect_options *ndo,
+                                         goto bad;
+                                 break;
+                             }
+-
++#endif
+                         case TCPOPT_FASTOPEN:
+                                 datalen = len - 2;
+                                 LENCHECK(datalen);
+@@ -720,6 +721,7 @@ tcp_print(netdissect_options *ndo,
+                 return;
+         }
+ 
++#ifndef TCPDUMP_MINI
+         if (ndo->ndo_packettype) {
+                 switch (ndo->ndo_packettype) {
+                 case PT_ZMTP1:
+@@ -735,12 +737,15 @@ tcp_print(netdissect_options *ndo,
+                 }
+                 return;
+         }
++#endif
+ 
+         if (IS_SRC_OR_DST_PORT(FTP_PORT)) {
+                 ND_PRINT(": ");
+                 ftp_print(ndo, bp, length);
++#ifndef TCPDUMP_MINI
+         } else if (IS_SRC_OR_DST_PORT(SSH_PORT)) {
+                 ssh_print(ndo, bp, length);
++#endif
+         } else if (IS_SRC_OR_DST_PORT(TELNET_PORT)) {
+                 telnet_print(ndo, bp, length);
+         } else if (IS_SRC_OR_DST_PORT(SMTP_PORT)) {
+@@ -759,10 +764,12 @@ tcp_print(netdissect_options *ndo,
+         } else if (IS_SRC_OR_DST_PORT(NETBIOS_SSN_PORT)) {
+                 nbt_tcp_print(ndo, bp, length);
+ #endif
++#ifndef TCPDUMP_MINI
+         } else if (IS_SRC_OR_DST_PORT(BGP_PORT)) {
+-                bgp_print(ndo, bp, length);
++                 bgp_print(ndo, bp, length);
+         } else if (IS_SRC_OR_DST_PORT(RPKI_RTR_PORT)) {
+                 rpki_rtr_print(ndo, bp, length);
++#endif
+ #ifdef ENABLE_SMB
+         } else if (IS_SRC_OR_DST_PORT(SMB_PORT)) {
+                 smb_tcp_print(ndo, bp, length);
+@@ -770,18 +777,22 @@ tcp_print(netdissect_options *ndo,
+         } else if (IS_SRC_OR_DST_PORT(RTSP_PORT)) {
+                 ND_PRINT(": ");
+                 rtsp_print(ndo, bp, length);
++#ifndef TCPDUMP_MINI
+         } else if (IS_SRC_OR_DST_PORT(MSDP_PORT)) {
+                 msdp_print(ndo, bp, length);
+         } else if (IS_SRC_OR_DST_PORT(LDP_PORT)) {
+                 ldp_print(ndo, bp, length);
+-        } else if (IS_SRC_OR_DST_PORT(PPTP_PORT))
++#endif
++        } else if (IS_SRC_OR_DST_PORT(PPTP_PORT)) {
+                 pptp_print(ndo, bp);
+-        else if (IS_SRC_OR_DST_PORT(REDIS_PORT))
++#ifndef TCPDUMP_MINI
++        } else if (IS_SRC_OR_DST_PORT(REDIS_PORT))
+                 resp_print(ndo, bp, length);
+         else if (IS_SRC_OR_DST_PORT(BEEP_PORT))
+                 beep_print(ndo, bp, length);
+         else if (IS_SRC_OR_DST_PORT(OPENFLOW_PORT_OLD) || IS_SRC_OR_DST_PORT(OPENFLOW_PORT_IANA)) {
+                 openflow_print(ndo, bp, length);
++#endif
+         } else if (IS_SRC_OR_DST_PORT(HTTP_PORT_ALT)) {
+                 ND_PRINT(": ");
+                 http_print(ndo, bp, length);
+--- a/print-udp.c
++++ b/print-udp.c
+@@ -433,10 +433,12 @@ udp_print(netdissect_options *ndo, const
+ 			vat_print(ndo, cp, length);
+ 			break;
+ 
++#ifndef TCPDUMP_MINI
+ 		case PT_WB:
+ 			udpipaddr_print(ndo, ip, sport, dport);
+ 			wb_print(ndo, cp, length);
+ 			break;
++#endif
+ 
+ 		case PT_RPC:
+ 			rp = (const struct sunrpc_msg *)cp;
+@@ -465,10 +467,12 @@ udp_print(netdissect_options *ndo, const
+ 			snmp_print(ndo, cp, length);
+ 			break;
+ 
++#ifndef TCPDUMP_MINI
+ 		case PT_CNFP:
+ 			udpipaddr_print(ndo, ip, sport, dport);
+ 			cnfp_print(ndo, cp);
+ 			break;
++#endif
+ 
+ 		case PT_TFTP:
+ 			udpipaddr_print(ndo, ip, sport, dport);
+@@ -485,6 +489,7 @@ udp_print(netdissect_options *ndo, const
+ 			radius_print(ndo, cp, length);
+ 			break;
+ 
++#ifndef TCPDUMP_MINI
+ 		case PT_VXLAN:
+ 			udpipaddr_print(ndo, ip, sport, dport);
+ 			vxlan_print(ndo, cp, length);
+@@ -507,6 +512,7 @@ udp_print(netdissect_options *ndo, const
+ 			udpipaddr_print(ndo, ip, sport, dport);
+ 			someip_print(ndo, cp, length);
+ 			break;
++#endif
+ 		case PT_DOMAIN:
+ 			udpipaddr_print(ndo, ip, sport, dport);
+ 			/* over_tcp: FALSE, is_mdns: FALSE */
+@@ -594,8 +600,12 @@ udp_print(netdissect_options *ndo, const
+ 			bootp_print(ndo, cp, length);
+ 		else if (IS_SRC_OR_DST_PORT(TFTP_PORT))
+ 			tftp_print(ndo, cp, length);
++#ifndef TCPDUMP_MINI
++#ifdef ENABLE_SMB
+ 		else if (IS_SRC_OR_DST_PORT(KERBEROS_PORT))
+ 			krb_print(ndo, (const u_char *)cp);
++#endif
++#endif
+ 		else if (IS_SRC_OR_DST_PORT(NTP_PORT))
+ 			ntp_print(ndo, cp, length);
+ #ifdef ENABLE_SMB
+@@ -607,6 +617,7 @@ udp_print(netdissect_options *ndo, const
+ 		else if (IS_SRC_OR_DST_PORT(SNMP_PORT) ||
+ 			 IS_SRC_OR_DST_PORT(SNMPTRAP_PORT))
+ 			snmp_print(ndo, cp, length);
++#ifndef TCPDUMP_MINI
+ 		else if (IS_SRC_OR_DST_PORT(PTP_EVENT_PORT) ||
+ 			 IS_SRC_OR_DST_PORT(PTP_GENERAL_PORT))
+ 			ptp_print(ndo, cp, length);
+@@ -614,38 +625,50 @@ udp_print(netdissect_options *ndo, const
+ 			cisco_autorp_print(ndo, cp, length);
+ 		else if (IS_SRC_OR_DST_PORT(ISAKMP_PORT))
+ 			 isakmp_print(ndo, cp, length, bp2);
++#endif
+ 		else if (IS_SRC_OR_DST_PORT(SYSLOG_PORT))
+ 			syslog_print(ndo, cp, length);
++#ifndef TCPDUMP_MINI
+ 		else if (IS_SRC_OR_DST_PORT(RIP_PORT))
+ 			rip_print(ndo, cp, length);
+ 		else if (IS_SRC_OR_DST_PORT(RIPNG_PORT))
+ 			ripng_print(ndo, cp, length);
+ 		else if (IS_SRC_OR_DST_PORT(TIMED_PORT))
+ 			timed_print(ndo, (const u_char *)cp);
++#endif
+ 		else if (IS_SRC_OR_DST_PORT(DHCP6_SERV_PORT) ||
+ 			 IS_SRC_OR_DST_PORT(DHCP6_CLI_PORT))
+ 			dhcp6_print(ndo, cp, length);
++#ifndef TCPDUMP_MINI
+ 		else if (IS_SRC_OR_DST_PORT(LDP_PORT))
+ 			ldp_print(ndo, cp, length);
+ 		else if (IS_SRC_OR_DST_PORT(AODV_PORT))
+ 			aodv_print(ndo, cp, length, IP_V(ip) == 6);
++#endif
+ 		else if (IS_SRC_OR_DST_PORT(OLSR_PORT))
+ 			olsr_print(ndo, cp, length, IP_V(ip) == 6);
++#ifndef TCPDUMP_MINI
+ 		else if (IS_SRC_OR_DST_PORT(LMP_PORT))
+ 			lmp_print(ndo, cp, length);
++#ifdef ENABLE_SMB
+ 		else if (IS_SRC_OR_DST_PORT(KERBEROS_SEC_PORT))
+ 			krb_print(ndo, (const u_char *)cp);
++#endif
+ 		else if (IS_SRC_OR_DST_PORT(LWRES_PORT))
+ 			lwres_print(ndo, cp, length);
+ 		else if (IS_SRC_OR_DST_PORT(MULTICASTDNS_PORT))
+ 			/* over_tcp: FALSE, is_mdns: TRUE */
+ 			domain_print(ndo, cp, length, FALSE, TRUE);
++#ifdef ENABLE_SMB
+ 		else if (IS_SRC_OR_DST_PORT(ISAKMP_PORT_NATT))
+ 			 isakmp_rfc3948_print(ndo, cp, length, bp2, IP_V(ip), fragmented, ttl_hl);
+ 		else if (IS_SRC_OR_DST_PORT(ISAKMP_PORT_USER1) || IS_SRC_OR_DST_PORT(ISAKMP_PORT_USER2))
+ 			isakmp_print(ndo, cp, length, bp2);
++#endif
++#endif
+ 		else if (IS_SRC_OR_DST_PORT(L2TP_PORT))
+ 			l2tp_print(ndo, cp, length);
++#ifndef TCPDUMP_MINI
+ 		else if (dport == VAT_PORT)
+ 			vat_print(ndo, cp, length);
+ 		else if (IS_SRC_OR_DST_PORT(ZEPHYR_SRV_PORT) || IS_SRC_OR_DST_PORT(ZEPHYR_CLT_PORT))
+@@ -669,6 +692,7 @@ udp_print(netdissect_options *ndo, const
+ 		 */
+ 		else if (dport == WB_PORT)
+ 			wb_print(ndo, cp, length);
++#endif
+ 		else if (IS_SRC_OR_DST_PORT(RADIUS_PORT) ||
+ 			 IS_SRC_OR_DST_PORT(RADIUS_NEW_PORT) ||
+ 			 IS_SRC_OR_DST_PORT(RADIUS_ACCOUNTING_PORT) ||
+@@ -676,6 +700,7 @@ udp_print(netdissect_options *ndo, const
+ 			 IS_SRC_OR_DST_PORT(RADIUS_CISCO_COA_PORT) ||
+ 			 IS_SRC_OR_DST_PORT(RADIUS_COA_PORT) )
+ 			radius_print(ndo, cp, length);
++#ifndef TCPDUMP_MINI
+ 		else if (dport == HSRP_PORT)
+ 			hsrp_print(ndo, cp, length);
+ 		else if (IS_SRC_OR_DST_PORT(MPLS_LSP_PING_PORT))
+@@ -695,8 +720,10 @@ udp_print(netdissect_options *ndo, const
+ 			lwapp_control_print(ndo, cp, length, 0);
+ 		else if (IS_SRC_OR_DST_PORT(LWAPP_DATA_PORT))
+ 			lwapp_data_print(ndo, cp, length);
++#endif
+ 		else if (IS_SRC_OR_DST_PORT(SIP_PORT))
+ 			sip_print(ndo, cp, length);
++#ifndef TCPDUMP_MINI
+ 		else if (IS_SRC_OR_DST_PORT(OTV_PORT))
+ 			otv_print(ndo, cp, length);
+ 		else if (IS_SRC_OR_DST_PORT(VXLAN_PORT))
+@@ -721,6 +748,7 @@ udp_print(netdissect_options *ndo, const
+ 			someip_print(ndo, cp, length);
+ 		else if (sport == BCM_LI_PORT)
+ 			bcm_li_print(ndo, cp, length);
++#endif
+ 		else {
+ 			if (ulen > length && !fragmented)
+ 				ND_PRINT("UDP, bad length %u > %u",
+--- a/print.c
++++ b/print.c
+@@ -46,6 +46,7 @@ struct printer {
+ };
+ 
+ static const struct printer printers[] = {
++#ifndef TCPDUMP_MINI
+ #ifdef DLT_APPLE_IP_OVER_IEEE1394
+ 	{ ap1394_if_print,	DLT_APPLE_IP_OVER_IEEE1394 },
+ #endif
+@@ -84,7 +85,9 @@ static const struct printer printers[] =
+ #ifdef DLT_ENC
+ 	{ enc_if_print,		DLT_ENC },
+ #endif
++#endif
+ 	{ ether_if_print,	DLT_EN10MB },
++#ifndef TCPDUMP_MINI
+ 	{ fddi_if_print,	DLT_FDDI },
+ #ifdef DLT_FR
+ 	{ fr_if_print,		DLT_FR },
+@@ -92,6 +95,7 @@ static const struct printer printers[] =
+ #ifdef DLT_FRELAY
+ 	{ fr_if_print,		DLT_FRELAY },
+ #endif
++#endif
+ #ifdef DLT_IEEE802_11
+ 	{ ieee802_11_if_print,	DLT_IEEE802_11},
+ #endif
+@@ -101,6 +105,7 @@ static const struct printer printers[] =
+ #ifdef DLT_IEEE802_11_RADIO
+ 	{ ieee802_11_radio_if_print,	DLT_IEEE802_11_RADIO },
+ #endif
++#ifndef TCPDUMP_MINI
+ #ifdef DLT_IEEE802_15_4
+ 	{ ieee802_15_4_if_print, DLT_IEEE802_15_4 },
+ #endif
+@@ -113,9 +118,11 @@ static const struct printer printers[] =
+ #ifdef DLT_IP_OVER_FC
+ 	{ ipfc_if_print,	DLT_IP_OVER_FC },
+ #endif
++#endif
+ #ifdef DLT_IPNET
+ 	{ ipnet_if_print,	DLT_IPNET },
+ #endif
++#ifndef TCPDUMP_MINI
+ #ifdef DLT_IPOIB
+ 	{ ipoib_if_print,       DLT_IPOIB },
+ #endif
+@@ -170,19 +177,23 @@ static const struct printer printers[] =
+ #ifdef DLT_MFR
+ 	{ mfr_if_print,		DLT_MFR },
+ #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_if_print,	DLT_NULL },
+ #ifdef DLT_LOOP
+ 	{ null_if_print,	DLT_LOOP },
+ #endif
++#ifndef TCPDUMP_MINI
+ #ifdef DLT_PFLOG
+ 	{ pflog_if_print,	DLT_PFLOG },
+ #endif
+@@ -198,6 +209,7 @@ static const struct printer printers[] =
+ #ifdef DLT_PPP_SERIAL
+ 	{ ppp_hdlc_if_print,	DLT_PPP_SERIAL },
+ #endif
++#endif
+ 	{ ppp_if_print,		DLT_PPP },
+ #ifdef DLT_PPP_PPPD
+ 	{ ppp_if_print,		DLT_PPP_PPPD },
+@@ -209,6 +221,7 @@ static const struct printer printers[] =
+ 	{ prism_if_print,	DLT_PRISM_HEADER },
+ #endif
+ 	{ raw_if_print,		DLT_RAW },
++#ifndef TCPDUMP_MINI
+ #ifdef DLT_IPV4
+ 	{ raw_if_print,		DLT_IPV4 },
+ #endif
+@@ -241,6 +254,7 @@ static const struct printer printers[] =
+ #ifdef DLT_VSOCK
+ 	{ vsock_if_print,	DLT_VSOCK },
+ #endif
++#endif
+ 	{ NULL,                 0 },
+ };
+ 
diff --git a/package/network/utils/umbim/Makefile b/package/network/utils/umbim/Makefile
new file mode 100644
index 0000000..39c30d7
--- /dev/null
+++ b/package/network/utils/umbim/Makefile
@@ -0,0 +1,44 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=umbim
+PKG_RELEASE:=25
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL=$(PROJECT_GIT)/project/umbim.git
+PKG_SOURCE_DATE:=2022-08-13
+PKG_SOURCE_VERSION:=146bc77c98ace3d1cc672986669650d2e1da71f3
+PKG_MIRROR_HASH:=9eae9f191e9c4a8132dba32e356047b8dfd62556f06800f05a283630cfed472a
+PKG_MAINTAINER:=John Crispin <john@phrozen.org>
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=
+
+PKG_FLAGS:=nonshared
+PKG_BUILD_FLAGS:=gc-sections
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/umbim
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=WWAN
+  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
+
+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..75b914e
--- /dev/null
+++ b/package/network/utils/umbim/files/lib/netifd/proto/mbim.sh
@@ -0,0 +1,336 @@
+#!/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_boolean allow_roaming
+	proto_config_add_boolean allow_partner
+	proto_config_add_string auth
+	proto_config_add_string username
+	proto_config_add_string password
+	[ -e /proc/sys/net/ipv6 ] && proto_config_add_string ipv6
+	proto_config_add_string dhcp
+	proto_config_add_string dhcpv6
+	proto_config_add_boolean sourcefilter
+	proto_config_add_boolean delegate
+	proto_config_add_string pdptype
+	proto_config_add_int mtu
+	proto_config_add_defaults
+}
+
+_proto_mbim_get_field() {
+        local field="$1"
+        shift
+        local mbimconfig="$@"
+        echo "$mbimconfig" | while read -r line; do
+                variable=${line%%:*}
+                [ "$variable" = "$field" ] || continue;
+                value=${line##* }
+                echo -n "$value "
+        done
+}
+
+_proto_mbim_setup() {
+	local interface="$1"
+	local tid=2
+	local ret
+
+	local device apn pincode delay auth username password allow_roaming allow_partner
+	local dhcp dhcpv6 pdptype ip4table ip6table mtu $PROTO_DEFAULT_OPTIONS
+	json_get_vars device apn pincode delay auth username password allow_roaming allow_partner
+	json_get_vars dhcp dhcpv6 sourcefilter delegate pdptype ip4table ip6table mtu $PROTO_DEFAULT_OPTIONS
+
+	[ ! -e /proc/sys/net/ipv6 ] && ipv6=0 || json_get_var ipv6 ipv6
+
+	[ -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"
+		tid=$((tid + 1))
+		umbim $DBG -t $tid -d "$device" disconnect
+		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"
+			tid=$((tid + 1))
+			umbim $DBG -t $tid -d "$device" disconnect
+			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
+	[ $? -eq 2 ] && {
+		echo "mbim[$$]" "PIN required"
+		tid=$((tid + 1))
+		umbim $DBG -t $tid -d "$device" disconnect
+		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"
+		tid=$((tid + 1))
+		umbim $DBG -t $tid -d "$device" disconnect
+		proto_notify_error "$interface" NO_SUBSCRIBER
+		return 1
+	}
+	tid=$((tid + 1))
+
+	echo "mbim[$$]" "Register with network"
+	connected=0
+	umbim $DBG -n -t $tid -d $device registration
+	reg_status=$?
+	case $reg_status in
+		0)	echo "mbim[$$]" "Registered in home mode"
+			tid=$((tid + 1))
+			connected=1;;
+		4)	if [ "$allow_roaming" = "1" ]; then
+				echo "mbim[$$]" "Registered in roaming mode"
+				tid=$((tid + 1))
+				connected=1
+			fi;;
+		5) 	if [ "$allow_partner" = "1" ]; then
+				echo "mbim[$$]" "Registered in partner mode"
+				tid=$((tid + 1))
+				connected=1
+			fi;;
+	esac
+	if [ $connected -ne 1 ]; then
+		echo "mbim[$$]" "Subscriber registration failed (code $reg_status)"
+		tid=$((tid + 1))
+		umbim $DBG -t $tid -d "$device" disconnect
+		proto_notify_error "$interface" NO_REGISTRATION
+		return 1
+	fi
+
+	echo "mbim[$$]" "Attach to network"
+	umbim $DBG -n -t $tid -d $device attach || {
+		echo "mbim[$$]" "Failed to attach to network"
+		tid=$((tid + 1))
+		umbim $DBG -t $tid -d "$device" disconnect
+		proto_notify_error "$interface" ATTACH_FAILED
+		return 1
+	}
+	tid=$((tid + 1))
+
+	pdptype=$(echo "$pdptype" | awk '{print tolower($0)}')
+	[ "$ipv6" = 0 ] && pdptype="ipv4"
+
+	local req_pdptype="" # Pass "default" PDP type to umbim if unconfigured
+	[ "$pdptype" = "ipv4" -o "$pdptype" = "ipv6" -o "$pdptype" = "ipv4v6" ] && req_pdptype="$pdptype:"
+
+	local connect_state
+	echo "mbim[$$]" "Connect to network"
+	connect_state=$(umbim $DBG -n -t $tid -d $device connect "$req_pdptype$apn" "$auth" "$username" "$password") || {
+		echo "mbim[$$]" "Failed to connect bearer"
+		tid=$((tid + 1))
+		umbim $DBG -t $tid -d "$device" disconnect
+		proto_notify_error "$interface" CONNECT_FAILED
+		return 1
+	}
+	tid=$((tid + 1))
+
+	echo "$connect_state"
+	local iptype="$(echo "$connect_state" | grep iptype: | awk '{print $4}')"
+
+	echo "mbim[$$]" "Connected"
+
+	local zone="$(fw3 -q network "$interface" 2>/dev/null)"
+
+	echo "mbim[$$]" "Setting up $ifname"
+	local mbimconfig="$(umbim $DBG -n -t $tid -d $device config)"
+	echo "$mbimconfig"
+	tid=$((tid + 1))
+
+	proto_init_update "$ifname" 1
+	proto_send_update "$interface"
+
+	[ -z "$dhcp" ] && dhcp="auto"
+	[ -z "$dhcpv6" ] && dhcpv6="auto"
+
+	[ "$iptype" != "ipv6" ] && {
+		json_init
+		json_add_string name "${interface}_4"
+		json_add_string ifname "@$interface"
+		ipv4address=$(_proto_mbim_get_field ipv4address "$mbimconfig")
+		if [ -n "$ipv4address" -a "$dhcp" != 1 ]; then
+			json_add_string proto "static"
+
+			json_add_array ipaddr
+			for address in $ipv4address; do
+				json_add_string "" "$address"
+			done
+			json_close_array
+
+			json_add_string gateway $(_proto_mbim_get_field ipv4gateway "$mbimconfig")
+		elif [ "$dhcp" != 0 ]; then
+			echo "mbim[$$]" "Starting DHCP on $ifname"
+			json_add_string proto "dhcp"
+		fi
+
+		[ "$peerdns" = 0 -a "$dhcp" != 1 ] || {
+			json_add_array dns
+			for server in $(_proto_mbim_get_field ipv4dnsserver "$mbimconfig"); do
+				json_add_string "" "$server"
+			done
+			json_close_array
+		}
+
+		proto_add_dynamic_defaults
+		[ -n "$zone" ] && json_add_string zone "$zone"
+		[ -n "$ip4table" ] && json_add_string ip4table "$ip4table"
+		json_close_object
+		ubus call network add_dynamic "$(json_dump)"
+	}
+
+	[ "$iptype" != "ipv4" ] && {
+		json_init
+		json_add_string name "${interface}_6"
+		json_add_string ifname "@$interface"
+		ipv6address=$(_proto_mbim_get_field ipv6address "$mbimconfig")
+		if [ -n "$ipv6address" -a "$dhcpv6" != 1 ]; then
+			json_add_string proto "static"
+
+			json_add_array ip6addr
+			for address in $ipv6address; do
+				json_add_string "" "$address"
+			done
+			json_close_array
+
+			json_add_array ip6prefix
+			for address in $ipv6address; do
+				json_add_string "" "$address"
+			done
+			json_close_array
+
+			json_add_string ip6gw $(_proto_mbim_get_field ipv6gateway "$mbimconfig")
+
+		elif [ "$dhcpv6" != 0 ]; then
+			echo "mbim[$$]" "Starting DHCPv6 on $ifname"
+			json_add_string proto "dhcpv6"
+			json_add_string extendprefix 1
+			[ "$delegate" = "0" ] && json_add_boolean delegate "0"
+			[ "$sourcefilter" = "0" ] && json_add_boolean sourcefilter "0"
+		fi
+
+		[ "$peerdns" = 0 -a "$dhcpv6" != 1 ] || {
+			json_add_array dns
+			for server in $(_proto_mbim_get_field ipv6dnsserver "$mbimconfig"); do
+				json_add_string "" "$server"
+			done
+			json_close_array
+		}
+
+		proto_add_dynamic_defaults
+		[ -n "$zone" ] && json_add_string zone "$zone"
+		[ -n "$ip6table" ] && json_add_string ip6table "$ip6table"
+		json_close_object
+		ubus call network add_dynamic "$(json_dump)"
+	}
+
+	[ -z "$mtu" ] && {
+		local ipv4mtu=$(_proto_mbim_get_field ipv4mtu "$mbimconfig")
+		ipv4mtu="${ipv4mtu:-0}"
+		local ipv6mtu=$(_proto_mbim_get_field ipv6mtu "$mbimconfig")
+		ipv6mtu="${ipv6mtu:-0}"
+
+		mtu=$((ipv6mtu > ipv4mtu ? ipv6mtu : ipv4mtu))
+	}
+	[ -n "$mtu" -a "$mtu" != 0 ] && {
+		echo Setting MTU of $ifname to $mtu
+		/sbin/ip link set dev $ifname mtu $mtu
+	}
+
+	uci_set_state network $interface tid "$tid"
+}
+
+proto_mbim_setup() {
+	local ret
+
+	_proto_mbim_setup $@
+	ret=$?
+
+	[ "$ret" = 0 ] || {
+		logger "mbim bringup failed, retry in 15s"
+		sleep 15
+	}
+
+	return $ret
+}
+
+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..54e1b4f
--- /dev/null
+++ b/package/network/utils/uqmi/Makefile
@@ -0,0 +1,48 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=uqmi
+PKG_RELEASE:=2
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL=$(PROJECT_GIT)/project/uqmi.git
+PKG_SOURCE_DATE:=2024-08-25
+PKG_SOURCE_VERSION:=28b48a10dbcd1177095b73c6d8086d10114f49b8
+PKG_MIRROR_HASH:=ca4c07775185b873da572d973b9bbce86198d41d921a8d32b990da34e5ffd65d
+PKG_MAINTAINER:=Matti Laakso <malaakso@elisanet.fi>
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=
+
+PKG_FLAGS:=nonshared
+PKG_BUILD_FLAGS:=gc-sections
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/uqmi
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=WWAN
+  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 \
+	-Wno-error=maybe-uninitialized
+
+CMAKE_OPTIONS += \
+	-DDEBUG=1
+
+define Package/uqmi/install
+	$(INSTALL_DIR) $(1)/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/uqmi/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..8ec577a
--- /dev/null
+++ b/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh
@@ -0,0 +1,535 @@
+#!/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 v6apn
+	proto_config_add_string auth
+	proto_config_add_string username
+	proto_config_add_string password
+	proto_config_add_string pincode
+	proto_config_add_int delay
+	proto_config_add_string modes
+	proto_config_add_string pdptype
+	proto_config_add_int profile
+	proto_config_add_int v6profile
+	proto_config_add_boolean dhcp
+	proto_config_add_boolean dhcpv6
+	proto_config_add_boolean sourcefilter
+	proto_config_add_boolean delegate
+	proto_config_add_boolean autoconnect
+	proto_config_add_int plmn
+	proto_config_add_int timeout
+	proto_config_add_int mtu
+	proto_config_add_defaults
+}
+
+proto_qmi_setup() {
+	local interface="$1"
+	local dataformat connstat plmn_mode mcc mnc
+	local device apn v6apn auth username password pincode delay modes pdptype
+	local profile v6profile dhcp dhcpv6 autoconnect plmn timeout mtu $PROTO_DEFAULT_OPTIONS
+	local ip4table ip6table
+	local cid_4 pdh_4 cid_6 pdh_6
+	local ip_6 ip_prefix_length gateway_6 dns1_6 dns2_6
+	local profile_pdptype
+
+	json_get_vars device apn v6apn auth username password pincode delay modes
+	json_get_vars pdptype profile v6profile dhcp dhcpv6 sourcefilter delegate autoconnect plmn ip4table
+	json_get_vars ip6table timeout mtu $PROTO_DEFAULT_OPTIONS
+
+	[ "$timeout" = "" ] && timeout="10"
+
+	[ "$metric" = "" ] && metric="0"
+
+	[ -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
+	}
+
+	[ -n "$delay" ] && sleep "$delay"
+
+	device="$(readlink -f $device)"
+	[ -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 "$mtu" ] && {
+		echo "Setting MTU to $mtu"
+		/sbin/ip link set dev $ifname mtu $mtu
+	}
+
+	echo "Waiting for SIM initialization"
+	local uninitialized_timeout=0
+	# timeout 3s for first call to avoid hanging uqmi
+	uqmi -d "$device" -t 3000 --get-pin-status > /dev/null 2>&1
+	while uqmi -s -d "$device" -t 1000 --get-pin-status | grep '"UIM uninitialized"' > /dev/null; do
+		[ -e "$device" ] || return 1
+		if [ "$uninitialized_timeout" -lt "$timeout" -o "$timeout" = "0" ]; then
+			let uninitialized_timeout++
+			sleep 1;
+		else
+			echo "SIM not initialized"
+			proto_notify_error "$interface" SIM_NOT_INITIALIZED
+			proto_block_restart "$interface"
+			return 1
+		fi
+	done
+
+	# Check if UIM application is stuck in illegal state
+	local uim_state_timeout=0
+	while true; do
+		json_load "$(uqmi -s -d "$device" -t 1000 --uim-get-sim-state)"
+		json_get_var card_application_state card_application_state
+
+		# SIM card is either completely absent or state is labeled as illegal
+		# Try to power-cycle the SIM card to recover from this state
+		if [ -z "$card_application_state" -o "$card_application_state" = "illegal" ]; then
+			echo "SIM in illegal state - Power-cycling SIM"
+
+			# Try to reset SIM application
+			uqmi -d "$device" -t 1000 --uim-power-off --uim-slot 1
+			sleep 3
+			uqmi -d "$device" -t 1000 --uim-power-on --uim-slot 1
+
+			if [ "$uim_state_timeout" -lt "$timeout" ] || [ "$timeout" = "0" ]; then
+				let uim_state_timeout++
+				sleep 1
+				continue
+			fi
+
+			# Recovery failed
+			proto_notify_error "$interface" SIM_ILLEGAL_STATE
+			proto_block_restart "$interface"
+			return 1
+		else
+			break
+		fi
+	done
+
+	if uqmi -s -d "$device" -t 1000 --uim-get-sim-state | grep -q '"Not supported"\|"Invalid QMI command"' &&
+	   uqmi -s -d "$device" -t 1000 --get-pin-status | grep -q '"Not supported"\|"Invalid QMI command"' ; then
+		[ -n "$pincode" ] && {
+			uqmi -s -d "$device" -t 1000 --verify-pin1 "$pincode" > /dev/null || uqmi -s -d "$device" -t 1000 --uim-verify-pin1 "$pincode" > /dev/null || {
+				echo "Unable to verify PIN"
+				proto_notify_error "$interface" PIN_FAILED
+				proto_block_restart "$interface"
+				return 1
+			}
+		}
+	else
+		json_load "$(uqmi -s -d "$device" -t 1000 --get-pin-status)"
+		json_get_var pin1_status pin1_status
+		if [ -z "$pin1_status" ]; then
+			json_load "$(uqmi -s -d "$device" -t 1000 --uim-get-sim-state)"
+			json_get_var pin1_status pin1_status
+		fi
+		json_get_var pin1_verify_tries pin1_verify_tries
+
+		case "$pin1_status" in
+			disabled)
+				echo "PIN verification is disabled"
+				;;
+			blocked)
+				echo "SIM locked PUK required"
+				proto_notify_error "$interface" PUK_NEEDED
+				proto_block_restart "$interface"
+				return 1
+				;;
+			not_verified)
+				[ "$pin1_verify_tries" -lt "3" ] && {
+					echo "PIN verify count value is $pin1_verify_tries this is below the limit of 3"
+					proto_notify_error "$interface" PIN_TRIES_BELOW_LIMIT
+					proto_block_restart "$interface"
+					return 1
+				}
+				if [ -n "$pincode" ]; then
+					uqmi -s -d "$device" -t 1000 --verify-pin1 "$pincode" > /dev/null 2>&1 || uqmi -s -d "$device" -t 1000 --uim-verify-pin1 "$pincode" > /dev/null 2>&1 || {
+						echo "Unable to verify PIN"
+						proto_notify_error "$interface" PIN_FAILED
+						proto_block_restart "$interface"
+						return 1
+					}
+				else
+					echo "PIN not specified but required"
+					proto_notify_error "$interface" PIN_NOT_SPECIFIED
+					proto_block_restart "$interface"
+					return 1
+				fi
+				;;
+			verified)
+				echo "PIN already verified"
+				;;
+			*)
+				echo "PIN status failed (${pin1_status:-sim_not_present})"
+				proto_notify_error "$interface" PIN_STATUS_FAILED
+				proto_block_restart "$interface"
+				return 1
+			;;
+		esac
+		json_cleanup
+	fi
+
+	if [ -n "$plmn" ]; then
+		json_load "$(uqmi -s -d "$device" -t 1000 --get-plmn)"
+		json_get_var plmn_mode mode
+		json_get_vars mcc mnc || {
+			mcc=0
+			mnc=0
+		}
+
+		if [ "$plmn" = "0" ]; then
+			if [ "$plmn_mode" != "automatic" ]; then
+				mcc=0
+				mnc=0
+				echo "Setting PLMN to auto"
+			fi
+		elif [ "$mcc" -ne "${plmn:0:3}" -o "$mnc" -ne "${plmn:3}" ]; then
+			mcc=${plmn:0:3}
+			mnc=${plmn:3}
+			echo "Setting PLMN to $plmn"
+		else
+			mcc=""
+			mnc=""
+		fi
+	fi
+
+	# Cleanup current state if any
+	uqmi -s -d "$device" -t 1000 --stop-network 0xffffffff --autoconnect > /dev/null 2>&1
+	uqmi -s -d "$device" -t 1000 --set-ip-family ipv6 --stop-network 0xffffffff --autoconnect > /dev/null 2>&1
+
+	# Go online
+	uqmi -s -d "$device" -t 1000 --set-device-operating-mode online > /dev/null 2>&1
+
+	# Set IP format
+	uqmi -s -d "$device" -t 1000 --set-data-format 802.3 > /dev/null 2>&1
+	uqmi -s -d "$device" -t 1000 --wda-set-data-format 802.3 > /dev/null 2>&1
+	dataformat="$(uqmi -s -d "$device" -t 1000 --wda-get-data-format)"
+
+	if [ "$dataformat" = '"raw-ip"' ]; then
+
+		[ -f /sys/class/net/$ifname/qmi/raw_ip ] || {
+			echo "Device only supports raw-ip mode but is missing this required driver attribute: /sys/class/net/$ifname/qmi/raw_ip"
+			return 1
+		}
+
+		echo "Device does not support 802.3 mode. Informing driver of raw-ip only for $ifname .."
+		echo "Y" > /sys/class/net/$ifname/qmi/raw_ip
+	fi
+
+	uqmi -s -d "$device" -t 1000 --sync > /dev/null 2>&1
+
+	uqmi -s -d "$device" -t 20000 --network-register > /dev/null 2>&1
+
+	# PLMN selection must happen after the call to network-register
+	if [ -n "$mcc" -a -n "$mnc" ]; then
+		uqmi -s -d "$device" -t 1000 --set-plmn --mcc "$mcc" --mnc "$mnc" > /dev/null 2>&1 || {
+			echo "Unable to set PLMN"
+			proto_notify_error "$interface" PLMN_FAILED
+			proto_block_restart "$interface"
+			return 1
+		}
+	fi
+
+	[ -n "$modes" ] && {
+		uqmi -s -d "$device" -t 1000 --set-network-modes "$modes" > /dev/null 2>&1
+		sleep 3
+		# Scan network to not rely on registration-timeout after RAT change
+		uqmi -s -d "$device" -t 30000 --network-scan > /dev/null 2>&1
+	}
+
+	echo "Waiting for network registration"
+	sleep 5
+	local registration_timeout=0
+	local registration_state=""
+	while true; do
+		registration_state=$(uqmi -s -d "$device" -t 1000 --get-serving-system 2>/dev/null | jsonfilter -e "@.registration" 2>/dev/null)
+
+		[ "$registration_state" = "registered" ] && break
+
+		if [ "$registration_state" = "searching" ] || [ "$registration_state" = "not_registered" ]; then
+			if [ "$registration_timeout" -lt "$timeout" ] || [ "$timeout" = "0" ]; then
+				[ "$registration_state" = "searching" ] || {
+					echo "Device stopped network registration. Restart network registration"
+					uqmi -s -d "$device" -t 20000 --network-register > /dev/null 2>&1
+				}
+				let registration_timeout++
+				sleep 1
+				continue
+			fi
+			echo "Network registration failed, registration timeout reached"
+		else
+			# registration_state is 'registration_denied' or 'unknown' or ''
+			echo "Network registration failed (reason: '$registration_state')"
+		fi
+
+		proto_notify_error "$interface" NETWORK_REGISTRATION_FAILED
+		return 1
+	done
+
+
+	echo "Starting network $interface"
+
+	pdptype="$(echo "$pdptype" | awk '{print tolower($0)}')"
+
+	[ "$pdptype" = "ip" -o "$pdptype" = "ipv6" -o "$pdptype" = "ipv4v6" ] || pdptype="ip"
+
+	# Configure PDP type and APN for profile 1.
+	# In case GGSN rejects IPv4v6 PDP, modem might not be able to
+	# establish a non-LTE data session.
+	profile_pdptype="$pdptype"
+	[ "$profile_pdptype" = "ip" ] && profile_pdptype="ipv4"
+	uqmi -s -d "$device" -t 1000 --modify-profile "3gpp,1" --apn "$apn" --pdp-type "$profile_pdptype" > /dev/null 2>&1
+
+	if [ "$pdptype" = "ip" ]; then
+		[ -z "$autoconnect" ] && autoconnect=1
+		[ "$autoconnect" = 0 ] && autoconnect=""
+	else
+		[ "$autoconnect" = 1 ] || autoconnect=""
+	fi
+
+	[ "$pdptype" = "ip" -o "$pdptype" = "ipv4v6" ] && {
+		cid_4=$(uqmi -s -d "$device" -t 1000 --get-client-id wds)
+		if ! [ "$cid_4" -eq "$cid_4" ] 2> /dev/null; then
+			echo "Unable to obtain client ID"
+			proto_notify_error "$interface" NO_CID
+			return 1
+		fi
+
+		uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --set-ip-family ipv4 > /dev/null 2>&1
+
+		pdh_4=$(uqmi -s -d "$device" -t 5000 --set-client-id wds,"$cid_4" \
+			--start-network \
+			${apn:+--apn $apn} \
+			${profile:+--profile $profile} \
+			${auth:+--auth-type $auth} \
+			${username:+--username $username} \
+			${password:+--password $password} \
+			${autoconnect:+--autoconnect})
+
+		# pdh_4 is a numeric value on success
+		if ! [ "$pdh_4" -eq "$pdh_4" ] 2> /dev/null; then
+			echo "Unable to connect IPv4"
+			uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1
+			proto_notify_error "$interface" CALL_FAILED
+			return 1
+		fi
+
+		# Check data connection state
+		connstat=$(uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --get-data-status)
+		[ "$connstat" == '"connected"' ] || {
+			echo "No data link!"
+			uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1
+			proto_notify_error "$interface" CALL_FAILED
+			return 1
+		}
+	}
+
+	[ "$pdptype" = "ipv6" -o "$pdptype" = "ipv4v6" ] && {
+		cid_6=$(uqmi -s -d "$device" -t 1000 --get-client-id wds)
+		if ! [ "$cid_6" -eq "$cid_6" ] 2> /dev/null; then
+			echo "Unable to obtain client ID"
+			proto_notify_error "$interface" NO_CID
+			return 1
+		fi
+
+		uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --set-ip-family ipv6 > /dev/null 2>&1
+
+		: "${v6apn:=${apn}}"
+		: "${v6profile:=${profile}}"
+
+		pdh_6=$(uqmi -s -d "$device" -t 5000 --set-client-id wds,"$cid_6" \
+			--start-network \
+			${v6apn:+--apn $v6apn} \
+			${v6profile:+--profile $v6profile} \
+			${auth:+--auth-type $auth} \
+			${username:+--username $username} \
+			${password:+--password $password} \
+			${autoconnect:+--autoconnect})
+
+		# pdh_6 is a numeric value on success
+		if ! [ "$pdh_6" -eq "$pdh_6" ] 2> /dev/null; then
+			echo "Unable to connect IPv6"
+			uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1
+			proto_notify_error "$interface" CALL_FAILED
+			return 1
+		fi
+
+		# Check data connection state
+		connstat=$(uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --set-ip-family ipv6 --get-data-status)
+		[ "$connstat" == '"connected"' ] || {
+			echo "No data link!"
+			uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1
+			proto_notify_error "$interface" CALL_FAILED
+			return 1
+		}
+	}
+
+	echo "Setting up $ifname"
+	proto_init_update "$ifname" 1
+	proto_set_keep 1
+	proto_add_data
+	[ -n "$pdh_4" ] && {
+		json_add_string "cid_4" "$cid_4"
+		json_add_string "pdh_4" "$pdh_4"
+	}
+	[ -n "$pdh_6" ] && {
+		json_add_string "cid_6" "$cid_6"
+		json_add_string "pdh_6" "$pdh_6"
+	}
+	proto_close_data
+	proto_send_update "$interface"
+
+	local zone="$(fw3 -q network "$interface" 2>/dev/null)"
+
+	[ -n "$pdh_6" ] && {
+		if [ -z "$dhcpv6" -o "$dhcpv6" = 0 ]; then
+			json_load "$(uqmi -s -d $device -t 1000 --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
+			proto_add_ipv6_address "$ip_6" "128"
+			proto_add_ipv6_prefix "${ip_6}/${ip_prefix_length}"
+			proto_add_ipv6_route "$gateway_6" "128"
+			[ "$defaultroute" = 0 ] || proto_add_ipv6_route "::0" 0 "$gateway_6" "" "" "${ip_6}/${ip_prefix_length}"
+			[ "$peerdns" = 0 ] || {
+				proto_add_dns_server "$dns1_6"
+				proto_add_dns_server "$dns2_6"
+			}
+			[ -n "$zone" ] && {
+				proto_add_data
+				json_add_string zone "$zone"
+				proto_close_data
+			}
+			proto_send_update "$interface"
+		else
+			json_init
+			json_add_string name "${interface}_6"
+			json_add_string ifname "@$interface"
+			[ "$pdptype" = "ipv4v6" ] && json_add_string iface_464xlat "0"
+			json_add_string proto "dhcpv6"
+			[ -n "$ip6table" ] && json_add_string ip6table "$ip6table"
+			proto_add_dynamic_defaults
+			# RFC 7278: Extend an IPv6 /64 Prefix to LAN
+			json_add_string extendprefix 1
+			[ "$delegate" = "0" ] && json_add_boolean delegate "0"
+			[ "$sourcefilter" = "0" ] && json_add_boolean sourcefilter "0"
+			[ -n "$zone" ] && json_add_string zone "$zone"
+			json_close_object
+			ubus call network add_dynamic "$(json_dump)"
+		fi
+	}
+
+	[ -n "$pdh_4" ] && {
+		if [ "$dhcp" = 0 ]; then
+			json_load "$(uqmi -s -d $device -t 1000 --set-client-id wds,$cid_4 --get-current-settings)"
+			json_select ipv4
+			json_get_var ip_4 ip
+			json_get_var gateway_4 gateway
+			json_get_var dns1_4 dns1
+			json_get_var dns2_4 dns2
+			json_get_var subnet_4 subnet
+
+			proto_init_update "$ifname" 1
+			proto_set_keep 1
+			proto_add_ipv4_address "$ip_4" "$subnet_4"
+			proto_add_ipv4_route "$gateway_4" "128"
+			[ "$defaultroute" = 0 ] || proto_add_ipv4_route "0.0.0.0" 0 "$gateway_4"
+			[ "$peerdns" = 0 ] || {
+				proto_add_dns_server "$dns1_4"
+				proto_add_dns_server "$dns2_4"
+			}
+			[ -n "$zone" ] && {
+				proto_add_data
+				json_add_string zone "$zone"
+				proto_close_data
+			}
+			proto_send_update "$interface"
+		else
+			json_init
+			json_add_string name "${interface}_4"
+			json_add_string ifname "@$interface"
+			json_add_string proto "dhcp"
+			[ -n "$ip4table" ] && json_add_string ip4table "$ip4table"
+			proto_add_dynamic_defaults
+			[ -n "$zone" ] && json_add_string zone "$zone"
+			json_close_object
+			ubus call network add_dynamic "$(json_dump)"
+		fi
+	}
+}
+
+qmi_wds_stop() {
+	local cid="$1"
+	local pdh="$2"
+
+	[ -n "$cid" ] || return
+
+	uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid" \
+		--stop-network 0xffffffff \
+		--autoconnect > /dev/null 2>&1
+
+	[ -n "$pdh" ] && {
+		uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid" \
+			--stop-network "$pdh" > /dev/null 2>&1
+	}
+
+	uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid" \
+		--release-client-id wds > /dev/null 2>&1
+}
+
+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 $interface"
+
+	json_load "$(ubus call network.interface.$interface status)"
+	json_select data
+	json_get_vars cid_4 pdh_4 cid_6 pdh_6
+
+	qmi_wds_stop "$cid_4" "$pdh_4"
+	qmi_wds_stop "$cid_6" "$pdh_6"
+
+	proto_init_update "*" 0
+	proto_send_update "$interface"
+}
+
+[ -n "$INCLUDE_ONLY" ] || {
+	add_protocol qmi
+}
diff --git a/package/network/utils/wireguard-tools/Makefile b/package/network/utils/wireguard-tools/Makefile
new file mode 100644
index 0000000..d704577
--- /dev/null
+++ b/package/network/utils/wireguard-tools/Makefile
@@ -0,0 +1,63 @@
+#
+# Copyright (C) 2016-2019 Jason A. Donenfeld <Jason@zx2c4.com>
+# Copyright (C) 2016 Baptiste Jonglez <openwrt@bitsofnetworks.org>
+# Copyright (C) 2016-2017 Dan Luedtke <mail@danrl.com>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=wireguard-tools
+
+PKG_VERSION:=1.0.20210914
+PKG_RELEASE:=4
+
+PKG_SOURCE:=wireguard-tools-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://git.zx2c4.com/wireguard-tools/snapshot/
+PKG_HASH:=97ff31489217bb265b7ae850d3d0f335ab07d2652ba1feec88b734bc96bd05ac
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=COPYING
+
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+MAKE_PATH:=src
+MAKE_VARS += PLATFORM=linux
+
+define Package/wireguard-tools
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=VPN
+  URL:=https://www.wireguard.com
+  MAINTAINER:=Jason A. Donenfeld <Jason@zx2c4.com>
+  TITLE:=WireGuard userspace control program (wg)
+  DEPENDS:= \
+	  +!BUSYBOX_CONFIG_IP:ip \
+	  +!BUSYBOX_CONFIG_FEATURE_IP_LINK:ip \
+	  +kmod-wireguard
+endef
+
+define Package/wireguard-tools/description
+  WireGuard is a novel VPN that runs inside the Linux Kernel and utilizes
+  state-of-the-art cryptography. It aims to be faster, simpler, leaner, and
+  more useful than IPSec, while avoiding the massive headache. It intends to
+  be considerably more performant than OpenVPN.  WireGuard is designed as a
+  general purpose VPN for running on embedded interfaces and super computers
+  alike, fit for many different circumstances. It uses UDP.
+
+  This package provides the userspace control program for WireGuard,
+  `wg(8)`, a netifd protocol helper, and a re-resolve watchdog script.
+endef
+
+define Package/wireguard-tools/install
+	$(INSTALL_DIR) $(1)/usr/bin/
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/wg $(1)/usr/bin/
+	$(INSTALL_BIN) ./files/wireguard_watchdog $(1)/usr/bin/
+	$(INSTALL_DIR) $(1)/lib/netifd/proto/
+	$(INSTALL_BIN) ./files/wireguard.sh $(1)/lib/netifd/proto/
+endef
+
+$(eval $(call BuildPackage,wireguard-tools))
diff --git a/package/network/utils/wireguard-tools/files/wireguard.sh b/package/network/utils/wireguard-tools/files/wireguard.sh
new file mode 100644
index 0000000..f6ad967
--- /dev/null
+++ b/package/network/utils/wireguard-tools/files/wireguard.sh
@@ -0,0 +1,217 @@
+#!/bin/sh
+# Copyright 2016-2017 Dan Luedtke <mail@danrl.com>
+# Licensed to the public under the Apache License 2.0.
+
+WG=/usr/bin/wg
+if [ ! -x $WG ]; then
+	logger -t "wireguard" "error: missing wireguard-tools (${WG})"
+	exit 0
+fi
+
+[ -n "$INCLUDE_ONLY" ] || {
+	. /lib/functions.sh
+	. ../netifd-proto.sh
+	init_proto "$@"
+}
+
+proto_wireguard_init_config() {
+	proto_config_add_string "private_key"
+	proto_config_add_int "listen_port"
+	proto_config_add_int "mtu"
+	proto_config_add_string "fwmark"
+	available=1
+	no_proto_task=1
+}
+
+proto_wireguard_setup_peer() {
+	local peer_config="$1"
+
+	local disabled
+	local public_key
+	local preshared_key
+	local allowed_ips
+	local route_allowed_ips
+	local endpoint_host
+	local endpoint_port
+	local persistent_keepalive
+
+	config_get_bool disabled "${peer_config}" "disabled" 0
+	config_get public_key "${peer_config}" "public_key"
+	config_get preshared_key "${peer_config}" "preshared_key"
+	config_get allowed_ips "${peer_config}" "allowed_ips"
+	config_get_bool route_allowed_ips "${peer_config}" "route_allowed_ips" 0
+	config_get endpoint_host "${peer_config}" "endpoint_host"
+	config_get endpoint_port "${peer_config}" "endpoint_port"
+	config_get persistent_keepalive "${peer_config}" "persistent_keepalive"
+
+	if [ "${disabled}" -eq 1 ]; then
+		# skip disabled peers
+		return 0
+	fi
+
+	if [ -z "$public_key" ]; then
+		echo "Skipping peer config $peer_config because public key is not defined."
+		return 0
+	fi
+
+	echo "[Peer]" >> "${wg_cfg}"
+	echo "PublicKey=${public_key}" >> "${wg_cfg}"
+	if [ "${preshared_key}" ]; then
+		echo "PresharedKey=${preshared_key}" >> "${wg_cfg}"
+	fi
+	for allowed_ip in $allowed_ips; do
+		echo "AllowedIPs=${allowed_ip}" >> "${wg_cfg}"
+	done
+	if [ "${endpoint_host}" ]; then
+		case "${endpoint_host}" in
+			*:*)
+				endpoint="[${endpoint_host}]"
+				;;
+			*)
+				endpoint="${endpoint_host}"
+				;;
+		esac
+		if [ "${endpoint_port}" ]; then
+			endpoint="${endpoint}:${endpoint_port}"
+		else
+			endpoint="${endpoint}:51820"
+		fi
+		echo "Endpoint=${endpoint}" >> "${wg_cfg}"
+	fi
+	if [ "${persistent_keepalive}" ]; then
+		echo "PersistentKeepalive=${persistent_keepalive}" >> "${wg_cfg}"
+	fi
+
+	if [ ${route_allowed_ips} -ne 0 ]; then
+		for allowed_ip in ${allowed_ips}; do
+			case "${allowed_ip}" in
+				*:*/*)
+					proto_add_ipv6_route "${allowed_ip%%/*}" "${allowed_ip##*/}"
+					;;
+				*.*/*)
+					proto_add_ipv4_route "${allowed_ip%%/*}" "${allowed_ip##*/}"
+					;;
+				*:*)
+					proto_add_ipv6_route "${allowed_ip%%/*}" "128"
+					;;
+				*.*)
+					proto_add_ipv4_route "${allowed_ip%%/*}" "32"
+					;;
+			esac
+		done
+	fi
+}
+
+ensure_key_is_generated() {
+	local private_key
+	private_key="$(uci get network."$1".private_key)"
+
+	if [ "$private_key" == "generate" ]; then
+		local ucitmp
+		oldmask="$(umask)"
+		umask 077
+		ucitmp="$(mktemp -d)"
+		private_key="$("${WG}" genkey)"
+		uci -q -t "$ucitmp" set network."$1".private_key="$private_key" && \
+			uci -q -t "$ucitmp" commit network
+		rm -rf "$ucitmp"
+		umask "$oldmask"
+	fi
+}
+
+proto_wireguard_setup() {
+	local config="$1"
+	local wg_dir="/tmp/wireguard"
+	local wg_cfg="${wg_dir}/${config}"
+
+	local private_key
+	local listen_port
+	local mtu
+
+	ensure_key_is_generated "${config}"
+
+	config_load network
+	config_get private_key "${config}" "private_key"
+	config_get listen_port "${config}" "listen_port"
+	config_get addresses "${config}" "addresses"
+	config_get mtu "${config}" "mtu"
+	config_get fwmark "${config}" "fwmark"
+	config_get ip6prefix "${config}" "ip6prefix"
+	config_get nohostroute "${config}" "nohostroute"
+	config_get tunlink "${config}" "tunlink"
+
+	ip link del dev "${config}" 2>/dev/null
+	ip link add dev "${config}" type wireguard
+
+	if [ "${mtu}" ]; then
+		ip link set mtu "${mtu}" dev "${config}"
+	fi
+
+	proto_init_update "${config}" 1
+
+	umask 077
+	mkdir -p "${wg_dir}"
+	echo "[Interface]" > "${wg_cfg}"
+	echo "PrivateKey=${private_key}" >> "${wg_cfg}"
+	if [ "${listen_port}" ]; then
+		echo "ListenPort=${listen_port}" >> "${wg_cfg}"
+	fi
+	if [ "${fwmark}" ]; then
+		echo "FwMark=${fwmark}" >> "${wg_cfg}"
+	fi
+	config_foreach proto_wireguard_setup_peer "wireguard_${config}"
+
+	# apply configuration file
+	${WG} setconf ${config} "${wg_cfg}"
+	WG_RETURN=$?
+
+	rm -f "${wg_cfg}"
+
+	if [ ${WG_RETURN} -ne 0 ]; then
+		sleep 5
+		proto_setup_failed "${config}"
+		exit 1
+	fi
+
+	for address in ${addresses}; do
+		case "${address}" in
+			*:*/*)
+				proto_add_ipv6_address "${address%%/*}" "${address##*/}"
+				;;
+			*.*/*)
+				proto_add_ipv4_address "${address%%/*}" "${address##*/}"
+				;;
+			*:*)
+				proto_add_ipv6_address "${address%%/*}" "128"
+				;;
+			*.*)
+				proto_add_ipv4_address "${address%%/*}" "32"
+				;;
+		esac
+	done
+
+	for prefix in ${ip6prefix}; do
+		proto_add_ipv6_prefix "$prefix"
+	done
+
+	# endpoint dependency
+	if [ "${nohostroute}" != "1" ]; then
+		wg show "${config}" endpoints | \
+		sed -E 's/\[?([0-9.:a-f]+)\]?:([0-9]+)/\1 \2/' | \
+		while IFS=$'\t ' read -r key address port; do
+			[ -n "${port}" ] || continue
+			proto_add_host_dependency "${config}" "${address}" "${tunlink}"
+		done
+	fi
+
+	proto_send_update "${config}"
+}
+
+proto_wireguard_teardown() {
+	local config="$1"
+	ip link del dev "${config}" >/dev/null 2>&1
+}
+
+[ -n "$INCLUDE_ONLY" ] || {
+	add_protocol wireguard
+}
diff --git a/package/network/utils/wireguard-tools/files/wireguard_watchdog b/package/network/utils/wireguard-tools/files/wireguard_watchdog
new file mode 100644
index 0000000..fc90f4a
--- /dev/null
+++ b/package/network/utils/wireguard-tools/files/wireguard_watchdog
@@ -0,0 +1,68 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2018 Aleksandr V. Piskunov <aleksandr.v.piskunov@gmail.com>.
+# Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+#
+# This watchdog script tries to re-resolve hostnames for inactive WireGuard peers.
+# Use it for peers with a frequently changing dynamic IP.
+# persistent_keepalive must be set, recommended value is 25 seconds.
+#
+# Run this script from cron every minute:
+# echo '* * * * * /usr/bin/wireguard_watchdog' >> /etc/crontabs/root
+
+
+. /lib/functions.sh
+
+check_peer_activity() {
+  local cfg=$1
+  local iface=$2
+  local disabled
+  local public_key
+  local endpoint_host
+  local endpoint_port
+  local persistent_keepalive
+  local last_handshake
+  local idle_seconds
+
+  config_get_bool disabled "${cfg}" "disabled" 0
+  config_get public_key "${cfg}" "public_key"
+  config_get endpoint_host "${cfg}" "endpoint_host"
+  config_get endpoint_port "${cfg}" "endpoint_port"
+
+  if [ "${disabled}" -eq 1 ]; then
+    # skip disabled peers
+    return 0
+  fi
+
+  persistent_keepalive=$(wg show ${iface} persistent-keepalive | grep ${public_key} | awk '{print $2}')
+
+  # only process peers with endpoints and keepalive set
+  [ -z ${endpoint_host} ] && return 0;
+  [ -z ${persistent_keepalive} -o ${persistent_keepalive} = "off" ] && return 0;
+
+  # skip IP addresses
+  # check taken from packages/net/ddns-scripts/files/dynamic_dns_functions.sh
+  local IPV4_REGEX="[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}"
+  local IPV6_REGEX="\(\([0-9A-Fa-f]\{1,4\}:\)\{1,\}\)\(\([0-9A-Fa-f]\{1,4\}\)\{0,1\}\)\(\(:[0-9A-Fa-f]\{1,4\}\)\{1,\}\)"
+  local IPV4=$(echo ${endpoint_host} | grep -m 1 -o "$IPV4_REGEX$")    # do not detect ip in 0.0.0.0.example.com
+  local IPV6=$(echo ${endpoint_host} | grep -m 1 -o "$IPV6_REGEX")
+  [ -n "${IPV4}" -o -n "${IPV6}" ] && return 0;
+
+  # re-resolve endpoint hostname if not responding for too long
+  last_handshake=$(wg show ${iface} latest-handshakes | grep ${public_key} | awk '{print $2}')
+  [ -z ${last_handshake} ] && return 0;
+  idle_seconds=$(($(date +%s)-${last_handshake}))
+  [ ${idle_seconds} -lt 150 ] && return 0;
+  logger -t "wireguard_monitor" "${iface} endpoint ${endpoint_host}:${endpoint_port} is not responding for ${idle_seconds} seconds, trying to re-resolve hostname"
+  wg set ${iface} peer ${public_key} endpoint "${endpoint_host}:${endpoint_port}"
+}
+
+# query ubus for all active wireguard interfaces
+eval $(ubus -S call network.interface dump | jsonfilter -e 'wg_ifaces=@.interface[@.up=true && @.proto="wireguard"].interface')
+
+# check every peer in every active wireguard interface
+config_load network
+for iface in $wg_ifaces; do
+  config_foreach check_peer_activity "wireguard_${iface}" "${iface}"
+done
diff --git a/package/network/utils/wireless-tools/Makefile b/package/network/utils/wireless-tools/Makefile
new file mode 100644
index 0000000..6ac66a0
--- /dev/null
+++ b/package/network/utils/wireless-tools/Makefile
@@ -0,0 +1,94 @@
+#
+# 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_CPE_ID:=cpe:/a:wireless_tools_project:wireless_tools
+PKG_VERSION:=29
+PKG_MINOR:=
+PKG_RELEASE:=6
+
+PKG_SOURCE:=wireless_tools.$(PKG_VERSION)$(PKG_MINOR).tar.gz
+PKG_SOURCE_URL:=https://hewlettpackard.github.io/wireless-tools
+PKG_HASH:=6fb80935fe208538131ce2c4178221bab1078a1656306bce8909c19887e2e5a1
+TAR_OPTIONS += || true
+
+PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
+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
+  ABI_VERSION:=29
+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,libiw))
+$(eval $(call BuildPackage,wireless-tools))
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..7b2cfe7
--- /dev/null
+++ b/package/network/utils/wpan-tools/Makefile
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=wpan-tools
+PKG_VERSION:=0.9
+PKG_RELEASE=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/linux-wpan/wpan-tools/releases/download/$(PKG_NAME)-$(PKG_VERSION)/$(PKG_NAME)-$(PKG_VERSION).tar.gz?
+PKG_HASH:=fa76d9c1874220e4b1f91c226f42baf1e372ea8ccf4b892effaf0d164448f608
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/wpan-tools
+  SECTION:=net
+  CATEGORY:=Network
+  TITLE:=cfg802154 interface configuration utility
+  URL:=https://linux-wpan.org/wpan-tools.html
+  DEPENDS:= +libnl
+endef
+
+define Package/wpan-tools/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/iwpan $(1)/usr/sbin/
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/wpan-ping/wpan-ping $(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..b02f9e1
--- /dev/null
+++ b/package/network/utils/wwan/Makefile
@@ -0,0 +1,45 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=wwan
+PKG_VERSION:=2019.04.29
+PKG_RELEASE=6
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=
+
+PKG_MAINTAINER:=John Crispin <john@phrozen.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/
+	#in order to keep the Lede GIT repo free of filenames with colons,
+	#we name the files xxxx-yyyy
+	# and rename here after copying to the build directory
+	shopt -s nullglob ; \
+	for filevar in $(1)/lib/network/wwan/*-* ; \
+	do \
+		FILENAME=$$$$(basename $$$$filevar) ; \
+		NEWNAME=$$$${FILENAME//-/:} ; \
+		mv "$(1)/lib/network/wwan/$$$$FILENAME" "$(1)/lib/network/wwan/$$$$NEWNAME" ; \
+	done
+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..c2ce008
--- /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..3ef6df4
--- /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..3ef6df4
--- /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..d219e7a
--- /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..e61bb09
--- /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..41c8afa
--- /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..14c2530
--- /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..0feb718
--- /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..e901589
--- /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..e901589
--- /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..42ec6fe
--- /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..b623ebf
--- /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..a01dea8
--- /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..3397252
--- /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..217038f
--- /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..17cc41d
--- /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..8944705
--- /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..be0a893
--- /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..3da9895
--- /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..a88c36d
--- /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..fc84354
--- /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..8230dd0
--- /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..77528b5
--- /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..e7d72f1
--- /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..e7d72f1
--- /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..e5b16e3
--- /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..126c09f
--- /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..126c09f
--- /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..fcdf611
--- /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..e042642
--- /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/0e8d-00a5 b/package/network/utils/wwan/files/data/0e8d-00a5
new file mode 100644
index 0000000..23a7ce3
--- /dev/null
+++ b/package/network/utils/wwan/files/data/0e8d-00a5
@@ -0,0 +1,5 @@
+{
+        "desc": "Medion S4222",
+        "control": 2,
+        "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..dab35fa
--- /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..b6da8c4
--- /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..142d70f
--- /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..842c0b4
--- /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..bb4b534
--- /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..0198c33
--- /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..a735680
--- /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..5a5194d
--- /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..aa50f5d
--- /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..fd80949
--- /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..532aadd
--- /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..71447d1
--- /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..43ccfd0
--- /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..d92732c
--- /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..d879a34
--- /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..b4780db
--- /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..447f681
--- /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..9617b69
--- /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..f0792c8
--- /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..ba1ea2a
--- /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..b959eca
--- /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..02967db
--- /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..900923c
--- /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..43ccfd0
--- /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..71447d1
--- /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..d92732c
--- /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..b5b13cc
--- /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..2f3a6d0
--- /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..497aff2
--- /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..0e3ebbb
--- /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..497aff2
--- /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..0e3ebbb
--- /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..497aff2
--- /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..497aff2
--- /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..4e667e7
--- /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..4e667e7
--- /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..4e667e7
--- /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..be1a659
--- /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..a912288
--- /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..90fe42b
--- /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..11859ac
--- /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..e23f53e
--- /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..11859ac
--- /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..e23f53e
--- /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..11859ac
--- /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..aca144d
--- /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..8df7e72
--- /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..c878825
--- /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..339f39a
--- /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..6dcb045
--- /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..09b482c
--- /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..ad5f049
--- /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..9bc6872
--- /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..9383e6c
--- /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..9383e6c
--- /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..bae654f
--- /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..7154b0c
--- /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..1e1c89c
--- /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..923302a
--- /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..9cd3ad0
--- /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..062c200
--- /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/1199-68c0 b/package/network/utils/wwan/files/data/1199-68c0
new file mode 100644
index 0000000..fedd6d7
--- /dev/null
+++ b/package/network/utils/wwan/files/data/1199-68c0
@@ -0,0 +1,4 @@
+{
+	"desc": "Sierra MC7304",
+	"type": "qmi"
+}
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..1b595cd
--- /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..7961908
--- /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..cd8cbdd
--- /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..342672a
--- /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..7961908
--- /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..3159714
--- /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..a73fdc4
--- /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..cbbf9d2
--- /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..c80d2e9
--- /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..ffa690d
--- /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..55696ff
--- /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..2228a90
--- /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..6eac38b
--- /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..6eac38b
--- /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..92f9b6a
--- /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..8419b69
--- /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..88a0f92
--- /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..9e575af
--- /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..b5a3f10
--- /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..9a0a292
--- /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..6345f53
--- /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..e8681e6
--- /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..52df7e2
--- /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..6eac38b
--- /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..6eac38b
--- /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..41aef76
--- /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..a36e1aa
--- /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..0702468
--- /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..f29b08f
--- /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..275d3a7
--- /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..a28901f
--- /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..4c8f576
--- /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..14012df
--- /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..d1c7615
--- /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..fc8404f
--- /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..1f18712
--- /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..fe656f5
--- /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..db1c68f
--- /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..6ec5735
--- /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..0ecddcf
--- /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..861c992
--- /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..861c992
--- /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..1c97f16
--- /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..0b9b226
--- /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..ac03ddc
--- /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..ac03ddc
--- /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..1ea46ea
--- /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..86d03ce
--- /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..203597d
--- /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..ea6d71f
--- /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..afeb681
--- /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..6225785
--- /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..96574f3
--- /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..8607d41
--- /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..8f0ff3b
--- /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..4ac52bb
--- /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..eeb3ea4
--- /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..9fd23cd
--- /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..9fd23cd
--- /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..323ec28
--- /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..d779cdf
--- /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..92c5f0d
--- /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..8301da1
--- /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..40ee5cb
--- /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..e0cbfe2
--- /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..f3866bb
--- /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..99fcedd
--- /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..8360921
--- /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..5b0d962
--- /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..5b0d962
--- /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..31c7421
--- /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..35dc57e
--- /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..0d7b826
--- /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..128bd72
--- /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..bcca7ff
--- /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..0bc992e
--- /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..3a6e72e
--- /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..1d0f0a1
--- /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..2b47841
--- /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..f8bbdae
--- /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..acd581c
--- /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..c2d52de
--- /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..2dbd3b5
--- /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..0527f6f
--- /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..be9cb55
--- /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..ed2fd26
--- /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..aac3158
--- /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..974edf4
--- /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..0cb57d9
--- /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..078932e
--- /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..db86581
--- /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..4208016
--- /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..f5b84eb
--- /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..e7eb5aa
--- /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..d91f388
--- /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..5d3e5a6
--- /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..7f6805b
--- /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..7f6805b
--- /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..b5113e9
--- /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..bad2bd8
--- /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..7155ac7
--- /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..9884b7d
--- /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..807068f
--- /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..807068f
--- /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..9884b7d
--- /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..9884b7d
--- /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..9884b7d
--- /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..9884b7d
--- /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..fa2c87d
--- /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..9884b7d
--- /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..9884b7d
--- /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..9884b7d
--- /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..1e19b2c
--- /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..58e392c
--- /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..c622100
--- /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..b58df70
--- /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..b58df70
--- /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..b58df70
--- /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..ae1da49
--- /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..e122028
--- /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..d561593
--- /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..3fe5f4b
--- /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..adf579c
--- /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..fb3d597
--- /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..fb3d597
--- /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..fb3d597
--- /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..faf9832
--- /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..517dbb8
--- /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..bf67e65
--- /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..bf67e65
--- /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..9e482b1
--- /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..b183834
--- /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..6f19f1f
--- /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..e96c51a
--- /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..8164eed
--- /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..5b445a3
--- /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..9ba190f
--- /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..ad488dd
--- /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..ad488dd
--- /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..0fbf6de
--- /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..e40cc86
--- /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..8786375
--- /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..8786375
--- /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..28566b3
--- /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..44f62eb
--- /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..fafcefd
--- /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..fafcefd
--- /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..dced60d
--- /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..efbb056
--- /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..5b83213
--- /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..b89257f
--- /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..5b83213
--- /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..d9088e9
--- /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..78d6148
--- /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/1e2d-0053 b/package/network/utils/wwan/files/data/1e2d-0053
new file mode 100644
index 0000000..e83f04c
--- /dev/null
+++ b/package/network/utils/wwan/files/data/1e2d-0053
@@ -0,0 +1,6 @@
+{
+	"desc": "Cinterion PH8",
+	"control": 2,
+	"data": 3
+}
+
diff --git a/package/network/utils/wwan/files/data/1e2d-005b b/package/network/utils/wwan/files/data/1e2d-005b
new file mode 100644
index 0000000..6678ff0
--- /dev/null
+++ b/package/network/utils/wwan/files/data/1e2d-005b
@@ -0,0 +1,5 @@
+{
+	"desc": "Cinterion ELS61",
+	"control": 1,
+	"data": 0
+}
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..3b5a3a2
--- /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..9f039b1
--- /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..9f039b1
--- /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..9f039b1
--- /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..07f1148
--- /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/2c7c-0125 b/package/network/utils/wwan/files/data/2c7c-0125
new file mode 100644
index 0000000..f58afa2
--- /dev/null
+++ b/package/network/utils/wwan/files/data/2c7c-0125
@@ -0,0 +1,4 @@
+{
+	"desc": "Quectel EC25",
+	"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..c0b7678
--- /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..3f99a0b
--- /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..ff18d6a
--- /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..c0b7678
--- /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..0404557
--- /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..c0b7678
--- /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..c0b7678
--- /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..7940b33
--- /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..7940b33
--- /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..7940b33
--- /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..fffa1e8
--- /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..fffa1e8
--- /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..fffa1e8
--- /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..e9aff09
--- /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..d3ac0d8
--- /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..d3ac0d8
--- /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..d3ac0d8
--- /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..575410b
--- /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..9907195
--- /dev/null
+++ b/package/network/utils/wwan/files/wwan.sh
@@ -0,0 +1,146 @@
+#!/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_config_add_string bus
+}
+
+proto_wwan_setup() {
+	local driver usb devicename desc bus
+
+	json_get_vars bus
+
+	if [ -L "/sys/bus/usb/devices/${bus}" ]; then
+		if [ -f "/sys/bus/usb/devices/${bus}/idVendor" ] \
+			&& [ -f "/sys/bus/usb/devices/${bus}/idProduct" ]; then
+			local vendor product
+			vendor=$(cat /sys/bus/usb/devices/${bus}/idVendor)
+			product=$(cat /sys/bus/usb/devices/${bus}/idProduct)
+			[ -f /lib/network/wwan/$vendor:$product ] && {
+				usb=/lib/network/wwan/$vendor:$product
+				devicename=$bus
+			}
+		else
+			echo "wwan[$$]" "Specified usb bus ${bus} was not found"
+			proto_notify_error "$interface" NO_USB
+			proto_block_restart "$interface"
+			return 1
+		fi
+	else
+		echo "wwan[$$]" "Searching for a valid wwan usb device..."
+		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
+	fi
+
+	echo "wwan[$$]" "Using wwan usb device on bus $devicename"
+
+	[ -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?* /sys/bus/usb/devices/$devicename/${devicename}*/tty/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 -e wwan -e usb); do
+		[ -z "$ctl_device" ] || continue
+		[ -n "$bus" ] && {
+			[ $(readlink /sys/class/net/$net | grep $bus) ] || 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_ether|*cdc_ncm)
+			ctl_device=/dev/$(cd /sys/class/net/$net/; find ../../../ -name ttyUSB* |xargs -n1 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_ether|*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_directip_teardown $@ ;;
+	comgt)			proto_3g_teardown $@ ;;
+	cdc_ether|*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..b757c1c
--- /dev/null
+++ b/package/network/utils/wwan/files/wwan.usb
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+[ "$ACTION" = add -a "$DEVTYPE" = usb_device ] || exit 0
+
+. /lib/functions.sh
+. /lib/netifd/netifd-proto.sh
+
+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..a86ff5d
--- /dev/null
+++ b/package/network/utils/wwan/files/wwan.usbmisc
@@ -0,0 +1,28 @@
+#!/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
+	fi
+	if [ "$ACTION" = remove ]; then
+		proto_set_available "$cfg" 0
+	fi
+	exit 0
+}
+
+config_load network
+config_foreach find_wwan_iface interface