Initial commit

This commit is contained in:
domenico
2025-06-24 13:14:22 +02:00
commit 4002f145fc
9002 changed files with 1731834 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
#
# Copyright (C) 2013-2016 OpenWrt.org
# Copyright (C) 2016 LEDE project
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=firewall
PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/firewall3.git
PKG_SOURCE_DATE:=2021-08-14
PKG_SOURCE_VERSION:=40e5f6a2bd0b5406eff7e1d2d4f95bbf8f9410a4
PKG_MIRROR_HASH:=4acd7d3c688d31a07ad871dcdbcd06d975ac86745d9f3a6caed68e694635965c
PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
PKG_LICENSE:=ISC
PKG_CONFIG_DEPENDS := CONFIG_IPV6
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/firewall
SECTION:=net
CATEGORY:=Base system
TITLE:=OpenWrt C Firewall
DEPENDS:=+libubox +libubus +libuci +libip4tc +IPV6:libip6tc +libxtables +kmod-ipt-core +kmod-ipt-conntrack +IPV6:kmod-nf-conntrack6 +kmod-ipt-nat
endef
define Package/firewall/description
This package provides a config-compatible C implementation of the UCI firewall.
endef
define Package/firewall/conffiles
/etc/config/firewall
/etc/firewall.user
endef
TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto
TARGET_LDFLAGS += -Wl,--gc-sections -flto
CMAKE_OPTIONS += $(if $(CONFIG_IPV6),,-DDISABLE_IPV6=1)
define Package/firewall/install
$(INSTALL_DIR) $(1)/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/firewall3 $(1)/sbin/fw3
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/firewall.init $(1)/etc/init.d/firewall
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
$(INSTALL_CONF) ./files/firewall.hotplug $(1)/etc/hotplug.d/iface/20-firewall
$(INSTALL_DIR) $(1)/etc/config/
$(INSTALL_CONF) ./files/firewall.config $(1)/etc/config/firewall
$(INSTALL_DIR) $(1)/etc/
$(INSTALL_CONF) ./files/firewall.user $(1)/etc/firewall.user
$(INSTALL_DIR) $(1)/usr/share/fw3
$(INSTALL_CONF) $(PKG_BUILD_DIR)/helpers.conf $(1)/usr/share/fw3
endef
$(eval $(call BuildPackage,firewall))

View File

@@ -0,0 +1,208 @@
config defaults
option syn_flood 1
option input ACCEPT
option output ACCEPT
option forward REJECT
# Uncomment this line to disable ipv6 rules
# option disable_ipv6 1
config zone
option name lan
list network 'lan'
option input ACCEPT
option output ACCEPT
option forward ACCEPT
config zone
option name wan
list network 'wan'
list network 'wan6'
option input REJECT
option output ACCEPT
option forward REJECT
option masq 1
option mtu_fix 1
config forwarding
option src lan
option dest wan
# We need to accept udp packets on port 68,
# see https://dev.openwrt.org/ticket/4108
config rule
option name Allow-DHCP-Renew
option src wan
option proto udp
option dest_port 68
option target ACCEPT
option family ipv4
# Allow IPv4 ping
config rule
option name Allow-Ping
option src wan
option proto icmp
option icmp_type echo-request
option family ipv4
option target ACCEPT
config rule
option name Allow-IGMP
option src wan
option proto igmp
option family ipv4
option target ACCEPT
# Allow DHCPv6 replies
# see https://dev.openwrt.org/ticket/10381
config rule
option name Allow-DHCPv6
option src wan
option proto udp
option src_ip fc00::/6
option dest_ip fc00::/6
option dest_port 546
option family ipv6
option target ACCEPT
config rule
option name Allow-MLD
option src wan
option proto icmp
option src_ip fe80::/10
list icmp_type '130/0'
list icmp_type '131/0'
list icmp_type '132/0'
list icmp_type '143/0'
option family ipv6
option target ACCEPT
# Allow essential incoming IPv6 ICMP traffic
config rule
option name Allow-ICMPv6-Input
option src wan
option proto icmp
list icmp_type echo-request
list icmp_type echo-reply
list icmp_type destination-unreachable
list icmp_type packet-too-big
list icmp_type time-exceeded
list icmp_type bad-header
list icmp_type unknown-header-type
list icmp_type router-solicitation
list icmp_type neighbour-solicitation
list icmp_type router-advertisement
list icmp_type neighbour-advertisement
option limit 1000/sec
option family ipv6
option target ACCEPT
# Allow essential forwarded IPv6 ICMP traffic
config rule
option name Allow-ICMPv6-Forward
option src wan
option dest *
option proto icmp
list icmp_type echo-request
list icmp_type echo-reply
list icmp_type destination-unreachable
list icmp_type packet-too-big
list icmp_type time-exceeded
list icmp_type bad-header
list icmp_type unknown-header-type
option limit 1000/sec
option family ipv6
option target ACCEPT
config rule
option name Allow-IPSec-ESP
option src wan
option dest lan
option proto esp
option target ACCEPT
config rule
option name Allow-ISAKMP
option src wan
option dest lan
option dest_port 500
option proto udp
option target ACCEPT
# allow interoperability with traceroute classic
# note that traceroute uses a fixed port range, and depends on getting
# back ICMP Unreachables. if we're operating in DROP mode, it won't
# work so we explicitly REJECT packets on these ports.
config rule
option name Support-UDP-Traceroute
option src wan
option dest_port 33434:33689
option proto udp
option family ipv4
option target REJECT
option enabled false
# include a file with users custom iptables rules
config include
option path /etc/firewall.user
### EXAMPLE CONFIG SECTIONS
# do not allow a specific ip to access wan
#config rule
# option src lan
# option src_ip 192.168.45.2
# option dest wan
# option proto tcp
# option target REJECT
# block a specific mac on wan
#config rule
# option dest wan
# option src_mac 00:11:22:33:44:66
# option target REJECT
# block incoming ICMP traffic on a zone
#config rule
# option src lan
# option proto ICMP
# option target DROP
# port redirect port coming in on wan to lan
#config redirect
# option src wan
# option src_dport 80
# option dest lan
# option dest_ip 192.168.16.235
# option dest_port 80
# option proto tcp
# port redirect of remapped ssh port (22001) on wan
#config redirect
# option src wan
# option src_dport 22001
# option dest lan
# option dest_port 22
# option proto tcp
### FULL CONFIG SECTIONS
#config rule
# option src lan
# option src_ip 192.168.45.2
# option src_mac 00:11:22:33:44:55
# option src_port 80
# option dest wan
# option dest_ip 194.25.2.129
# option dest_port 120
# option proto tcp
# option target REJECT
#config redirect
# option src lan
# option src_ip 192.168.45.2
# option src_mac 00:11:22:33:44:55
# option src_port 1024
# option src_dport 80
# option dest_ip 194.25.2.129
# option dest_port 120
# option proto tcp

View File

@@ -0,0 +1,11 @@
#!/bin/sh
[ "$ACTION" = ifup -o "$ACTION" = ifupdate ] || exit 0
[ "$ACTION" = ifupdate -a -z "$IFUPDATE_ADDRESSES" -a -z "$IFUPDATE_DATA" ] && exit 0
/etc/init.d/firewall enabled || exit 0
fw3 -q network "$INTERFACE" >/dev/null || exit 0
logger -t firewall "Reloading firewall due to $ACTION of $INTERFACE ($DEVICE)"
fw3 -q reload

View File

@@ -0,0 +1,61 @@
#!/bin/sh /etc/rc.common
START=19
USE_PROCD=1
QUIET=""
validate_firewall_redirect()
{
uci_validate_section firewall redirect "${1}" \
'proto:or(uinteger, string)' \
'src:string' \
'src_ip:cidr' \
'src_dport:or(port, portrange)' \
'dest:string' \
'dest_ip:cidr' \
'dest_port:or(port, portrange)' \
'target:or("SNAT", "DNAT")'
}
validate_firewall_rule()
{
uci_validate_section firewall rule "${1}" \
'proto:or(uinteger, string)' \
'src:string' \
'dest:string' \
'src_port:or(port, portrange)' \
'dest_port:or(port, portrange)' \
'target:string'
}
service_triggers() {
procd_add_reload_trigger firewall
procd_open_validate
validate_firewall_redirect
validate_firewall_rule
procd_close_validate
}
restart() {
fw3 restart
}
start_service() {
fw3 ${QUIET} start
}
stop_service() {
fw3 flush
}
reload_service() {
fw3 reload
}
boot() {
# Be silent on boot, firewall might be started by hotplug already,
# so don't complain in syslog.
QUIET=-q
start
}

View File

@@ -0,0 +1,7 @@
# This file is interpreted as shell script.
# Put your custom iptables rules here, they will
# be executed with each firewall (re-)start.
# Internal uci firewall chains are flushed and recreated on reload, so
# put custom rules into the root chains e.g. INPUT or FORWARD or into the
# special user chains, e.g. input_wan_rule or postrouting_lan_rule.

View File

@@ -0,0 +1,45 @@
#
# Copyright (C) 2021 Jo-Philipp Wich <jo@mein.io>
#
include $(TOPDIR)/rules.mk
PKG_NAME:=firewall4
PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/firewall4.git
PKG_SOURCE_DATE:=2021-09-01
PKG_SOURCE_VERSION:=cf835cecc8a449b2d2019f1ef4f085e535d5c1c1
PKG_MIRROR_HASH:=5798b76846107dde69a2a1ff3467f735b9a91a74106fbd6299d8a26eff70b9c2
PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
PKG_LICENSE:=ISC
include $(INCLUDE_DIR)/package.mk
define Package/firewall4
SECTION:=net
CATEGORY:=Base system
TITLE:=OpenWrt 4th gen firewall
DEPENDS:=+ucode +ucode-mod-fs +ucode-mod-uci +ucode-mod-ubus +kmod-nft-core +kmod-nft-fib +kmod-nft-nat +kmod-nft-nat6 +nftables-json
CONFLICTS:=firewall kmod-ipt-nat
endef
define Package/firewall4/description
This package provides an nftables-based implementation of the UCI firewall
sharing the same configuration format.
endef
define Package/firewall4/conffiles
/etc/config/firewall
/etc/nftables.d/
endef
define Package/firewall4/install
$(CP) -a $(PKG_BUILD_DIR)/root/* $(1)/
endef
define Build/Compile
endef
$(eval $(call BuildPackage,firewall4))

View File

@@ -0,0 +1,44 @@
#
# Copyright (C) 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:=gre
PKG_RELEASE:=13
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
define Package/gre/Default
endef
define Package/gre
SECTION:=net
CATEGORY:=Network
MAINTAINER:=Hans Dedecker <dedeckeh@gmail.com>
TITLE:=Generic Routing Encapsulation config support
DEPENDS:=+kmod-gre +IPV6:kmod-gre6 +resolveip
PROVIDES:=grev4 grev6
PKGARCH:=all
endef
define Package/gre/description
Generic Routing Encapsulation config support (IPv4 and IPv6) in /etc/config/network.
endef
define Build/Compile
endef
define Build/Configure
endef
define Package/gre/install
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/gre.sh $(1)/lib/netifd/proto/gre.sh
endef
$(eval $(call BuildPackage,gre))

View File

@@ -0,0 +1,296 @@
#!/bin/sh
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. /lib/functions/network.sh
. ../netifd-proto.sh
init_proto "$@"
}
gre_generic_setup() {
local cfg="$1"
local mode="$2"
local local="$3"
local remote="$4"
local link="$5"
local mtu ipv6 ttl tos zone ikey okey icsum ocsum iseqno oseqno multicast
json_get_vars mtu ipv6 ttl tos zone ikey okey icsum ocsum iseqno oseqno multicast
[ -z "$multicast" ] && multicast=1
proto_init_update "$link" 1
proto_add_tunnel
json_add_string mode "$mode"
json_add_int mtu "${mtu:-1280}"
json_add_boolean ipv6 "${ipv6:-1}"
[ -n "$df" ] && json_add_boolean df "$df"
[ -n "$ttl" ] && json_add_int ttl "$ttl"
[ -n "$tos" ] && json_add_string tos "$tos"
json_add_boolean multicast "$multicast"
json_add_string local "$local"
json_add_string remote "$remote"
[ -n "$tunlink" ] && json_add_string link "$tunlink"
json_add_object 'data'
[ -n "$ikey" ] && json_add_int ikey "$ikey"
[ -n "$okey" ] && json_add_int okey "$okey"
[ -n "$icsum" ] && json_add_boolean icsum "$icsum"
[ -n "$ocsum" ] && json_add_boolean ocsum "$ocsum"
[ -n "$iseqno" ] && json_add_boolean iseqno "$iseqno"
[ -n "$oseqno" ] && json_add_boolean oseqno "$oseqno"
[ -n "$encaplimit" ] && json_add_string encaplimit "$encaplimit"
json_close_object
proto_close_tunnel
proto_add_data
[ -n "$zone" ] && json_add_string zone "$zone"
proto_close_data
proto_send_update "$cfg"
}
gre_setup() {
local cfg="$1"
local mode="$2"
local remoteip
local ipaddr peeraddr
json_get_vars df ipaddr peeraddr tunlink nohostroute
[ -z "$peeraddr" ] && {
proto_notify_error "$cfg" "MISSING_PEER_ADDRESS"
proto_block_restart "$cfg"
exit
}
remoteip=$(resolveip -t 10 -4 "$peeraddr")
if [ -z "$remoteip" ]; then
proto_notify_error "$cfg" "PEER_RESOLVE_FAIL"
exit
fi
for ip in $remoteip; do
peeraddr=$ip
break
done
if [ "${nohostroute}" != "1" ]; then
( proto_add_host_dependency "$cfg" "$peeraddr" "$tunlink" )
fi
[ -z "$ipaddr" ] && {
local wanif="$tunlink"
if [ -z $wanif ] && ! network_find_wan wanif; then
proto_notify_error "$cfg" "NO_WAN_LINK"
exit
fi
if ! network_get_ipaddr ipaddr "$wanif"; then
proto_notify_error "$cfg" "NO_WAN_LINK"
exit
fi
}
[ -z "$df" ] && df="1"
case "$mode" in
gretapip)
gre_generic_setup $cfg $mode $ipaddr $peeraddr "gre4t-$cfg"
;;
*)
gre_generic_setup $cfg $mode $ipaddr $peeraddr "gre4-$cfg"
;;
esac
}
proto_gre_setup() {
local cfg="$1"
gre_setup $cfg "greip"
}
proto_gretap_setup() {
local cfg="$1"
local network
json_get_vars network
gre_setup $cfg "gretapip"
json_init
json_add_string name "gre4t-$cfg"
json_add_boolean link-ext 0
json_close_object
for i in $network; do
ubus call network.interface."$i" add_device "$(json_dump)"
done
}
grev6_setup() {
local cfg="$1"
local mode="$2"
local remoteip6
local ip6addr peer6addr weakif
json_get_vars ip6addr peer6addr tunlink weakif encaplimit nohostroute
[ -z "$peer6addr" ] && {
proto_notify_error "$cfg" "MISSING_PEER_ADDRESS"
proto_block_restart "$cfg"
exit
}
remoteip6=$(resolveip -t 10 -6 "$peer6addr")
if [ -z "$remoteip6" ]; then
proto_notify_error "$cfg" "PEER_RESOLVE_FAIL"
exit
fi
for ip6 in $remoteip6; do
peer6addr=$ip6
break
done
if [ "${nohostroute}" != "1" ]; then
( proto_add_host_dependency "$cfg" "$peer6addr" "$tunlink" )
fi
[ -z "$ip6addr" ] && {
local wanif="$tunlink"
if [ -z $wanif ] && ! network_find_wan6 wanif; then
proto_notify_error "$cfg" "NO_WAN_LINK"
exit
fi
if ! network_get_ipaddr6 ip6addr "$wanif"; then
[ -z "$weakif" ] && weakif="lan"
if ! network_get_ipaddr6 ip6addr "$weakif"; then
proto_notify_error "$cfg" "NO_WAN_LINK"
exit
fi
fi
}
case "$mode" in
gretapip6)
gre_generic_setup $cfg $mode $ip6addr $peer6addr "gre6t-$cfg"
;;
*)
gre_generic_setup $cfg $mode $ip6addr $peer6addr "gre6-$cfg"
;;
esac
}
proto_grev6_setup() {
local cfg="$1"
grev6_setup $cfg "greip6"
}
proto_grev6tap_setup() {
local cfg="$1"
local network
json_get_vars network
grev6_setup $cfg "gretapip6"
json_init
json_add_string name "gre6t-$cfg"
json_add_boolean link-ext 0
json_close_object
for i in $network; do
ubus call network.interface."$i" add_device "$(json_dump)"
done
}
gretap_generic_teardown() {
local network
json_get_vars network
json_init
json_add_string name "$1"
json_add_boolean link-ext 0
json_close_object
for i in $network; do
ubus call network.interface."$i" remove_device "$(json_dump)"
done
}
proto_gre_teardown() {
local cfg="$1"
}
proto_gretap_teardown() {
local cfg="$1"
gretap_generic_teardown "gre4t-$cfg"
}
proto_grev6_teardown() {
local cfg="$1"
}
proto_grev6tap_teardown() {
local cfg="$1"
gretap_generic_teardown "gre6t-$cfg"
}
gre_generic_init_config() {
no_device=1
available=1
proto_config_add_int "mtu"
proto_config_add_boolean "ipv6"
proto_config_add_int "ttl"
proto_config_add_string "tos"
proto_config_add_string "tunlink"
proto_config_add_string "zone"
proto_config_add_int "ikey"
proto_config_add_int "okey"
proto_config_add_boolean "icsum"
proto_config_add_boolean "ocsum"
proto_config_add_boolean "iseqno"
proto_config_add_boolean "oseqno"
proto_config_add_boolean "multicast"
}
proto_gre_init_config() {
gre_generic_init_config
proto_config_add_string "ipaddr"
proto_config_add_string "peeraddr"
proto_config_add_boolean "df"
proto_config_add_boolean "nohostroute"
}
proto_gretap_init_config() {
proto_gre_init_config
proto_config_add_string "network"
}
proto_grev6_init_config() {
gre_generic_init_config
proto_config_add_string "ip6addr"
proto_config_add_string "peer6addr"
proto_config_add_string "weakif"
proto_config_add_string "encaplimit"
proto_config_add_boolean "nohostroute"
}
proto_grev6tap_init_config() {
proto_grev6_init_config
proto_config_add_string "network"
}
[ -n "$INCLUDE_ONLY" ] || {
[ -d /sys/module/ip_gre ] && { add_protocol gre; add_protocol gretap; }
[ -d /sys/module/ip6_gre ] && { add_protocol grev6; add_protocol grev6tap; }
}

View File

@@ -0,0 +1,40 @@
#
# Copyright (C) 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:=ipip
PKG_RELEASE:=3
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
define Package/ipip
SECTION:=net
CATEGORY:=Network
MAINTAINER:=Hans Dedecker <dedeckeh@gmail.com>
TITLE:=IP in IP Tunnel config support
DEPENDS:= +kmod-ipip +resolveip
PKGARCH:=all
endef
define Package/ipip/description
IP in IP Tunnel config support in /etc/config/network.
endef
define Build/Compile
endef
define Build/Configure
endef
define Package/ipip/install
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/ipip.sh $(1)/lib/netifd/proto/ipip.sh
endef
$(eval $(call BuildPackage,ipip))

View File

@@ -0,0 +1,91 @@
#!/bin/sh
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. /lib/functions/network.sh
. ../netifd-proto.sh
init_proto "$@"
}
proto_ipip_setup() {
local cfg="$1"
local remoteip
local df ipaddr peeraddr tunlink ttl tos zone mtu
json_get_vars df ipaddr peeraddr tunlink ttl tos zone mtu
[ -z "$peeraddr" ] && {
proto_notify_error "$cfg" "MISSING_PEER_ADDRESS"
proto_block_restart "$cfg"
return
}
remoteip=$(resolveip -t 10 -4 "$peeraddr")
if [ -z "$remoteip" ]; then
proto_notify_error "$cfg" "PEER_RESOLVE_FAIL"
return
fi
for ip in $remoteip; do
peeraddr=$ip
break
done
( proto_add_host_dependency "$cfg" "$peeraddr" "$tunlink" )
[ -z "$ipaddr" ] && {
local wanif="$tunlink"
if [ -z $wanif ] && ! network_find_wan wanif; then
proto_notify_error "$cfg" "NO_WAN_LINK"
return
fi
if ! network_get_ipaddr ipaddr "$wanif"; then
proto_notify_error "$cfg" "NO_WAN_LINK"
return
fi
}
proto_init_update "ipip-$cfg" 1
proto_add_tunnel
json_add_string mode "ipip"
json_add_int mtu "${mtu:-1280}"
json_add_int ttl "${ttl:-64}"
[ -n "$tos" ] && json_add_string tos "$tos"
json_add_string local "$ipaddr"
json_add_string remote "$peeraddr"
[ -n "$tunlink" ] && json_add_string link "$tunlink"
json_add_boolean df "${df:-1}"
proto_close_tunnel
proto_add_data
[ -n "$zone" ] && json_add_string zone "$zone"
proto_close_data
proto_send_update "$cfg"
}
proto_ipip_teardown() {
local cfg="$1"
}
proto_ipip_init_config() {
no_device=1
available=1
proto_config_add_int "mtu"
proto_config_add_int "ttl"
proto_config_add_string "tos"
proto_config_add_string "tunlink"
proto_config_add_string "zone"
proto_config_add_string "ipaddr"
proto_config_add_string "peeraddr"
proto_config_add_boolean "df"
}
[ -n "$INCLUDE_ONLY" ] || {
add_protocol ipip
}

View File

@@ -0,0 +1,91 @@
#
# 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
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=dsl_cpe_control_danube
PKG_VERSION:=3.24.4.4
PKG_RELEASE:=10
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_BUILD_DIR:=$(BUILD_DIR)/dsl_cpe_control-$(PKG_VERSION)
PKG_SOURCE_URL:=@OPENWRT
PKG_HASH:=af0bdf45cc7a62e2b38d39aad4924dd83c24fae170ae5bbd8190c2a3d9106257
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
PKG_LICENSE:=BSD-3-Clause
PKG_FIXUP:=autoreconf
PKG_CONFIG_DEPENDS:=\
CONFIG_LTQ_DSL_ENABLE_SOAP \
CONFIG_LTQ_DSL_ENABLE_DSL_EVENT_POLLING
PKG_BUILD_DEPENDS:=ltq-adsl
PKG_FLAGS:=nonshared
include $(INCLUDE_DIR)/package.mk
define Package/ltq-adsl-app
SECTION:=net
CATEGORY:=Network
TITLE:=Lantiq DSL userland tool
URL:=http://www.lantiq.com/
DEPENDS:=@(TARGET_lantiq_xway||TARGET_lantiq_xway_legacy||TARGET_lantiq_ase) +libpthread +ltq-dsl-base +libubox +libubus
MENU:=1
endef
define Package/ltq-adsl-app/description
Infineon DSL CPE API for Amazon SE, Danube and Vinax.
endef
LTQ_DSL_MAX_DEVICE=1
LTQ_DSL_LINES_PER_DEVICE=1
LTQ_DSL_CHANNELS_PER_LINE=1
CONFIGURE_ARGS += \
--with-max-device="$(LTQ_DSL_MAX_DEVICE)" \
--with-lines-per-device="$(LTQ_DSL_LINES_PER_DEVICE)" \
--with-channels-per-line="$(LTQ_DSL_CHANNELS_PER_LINE)" \
--enable-danube \
--enable-driver-include="-I$(STAGING_DIR)/usr/include/adsl/" \
--enable-debug-prints \
--enable-add-appl-cflags="-DMAX_CLI_PIPES=2" \
--enable-cli-support \
--enable-cmv-scripts \
--enable-debug-tool-interface \
--enable-adsl-led \
--enable-dsl-ceoc \
--enable-script-notification \
--enable-dsl-pm \
--enable-dsl-pm-total \
--enable-dsl-pm-history \
--enable-dsl-pm-showtime \
--enable-dsl-pm-channel-counters \
--enable-dsl-pm-datapath-counters \
--enable-dsl-pm-line-counters \
--enable-dsl-pm-channel-thresholds \
--enable-dsl-pm-datapath-thresholds \
--enable-dsl-pm-line-thresholds \
--enable-dsl-pm-optional-parameters
TARGET_CFLAGS += -I$(LINUX_DIR)/include
define Build/Prepare
$(call Build/Prepare/Default)
$(CP) ../ltq-vdsl-app/src/src/dsl_cpe_ubus.c $(PKG_BUILD_DIR)/src/
endef
define Package/ltq-adsl-app/install
$(INSTALL_DIR) $(1)/etc/init.d $(1)/sbin $(1)/etc/hotplug.d/dsl
$(INSTALL_BIN) ./files/dsl_control $(1)/etc/init.d/
$(INSTALL_BIN) ./files/10_atm.sh $(1)/etc/hotplug.d/dsl
$(INSTALL_BIN) ./files/10_ptm.sh $(1)/etc/hotplug.d/dsl
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/dsl_cpe_control $(1)/sbin
endef
$(eval $(call BuildPackage,ltq-adsl-app))

View File

@@ -0,0 +1,29 @@
#!/bin/sh
[ "$DSL_NOTIFICATION_TYPE" = "DSL_STATUS" ] && \
[ "$DSL_TC_LAYER_STATUS" = "ATM" ] && \
! grep -q "ltq_atm_ar9\|ltq_atm_ase\|ltq_atm_danube" /proc/modules || exit 0
logger -p daemon.notice -t "dsl-notify" "Switching to TC-Layer ATM"
if grep -q "ltq_ptm_ar9\|ltq_ptm_ase\|ltq_ptm_danube" /proc/modules ; then
logger -p daemon.notice -t "dsl-notify" "Loading ATM driver while EFM/PTM driver is loaded is not possible. Reboot is needed."
exit
fi
case "$(strings /proc/device-tree/compatible)" in
*lantiq,ar9*)
soc="ar9"
;;
*lantiq,ase*)
soc="ase"
;;
*lantiq,danube*)
soc="danube"
;;
*)
logger -p daemon.notice -t "dsl-notify" "Unsupported SoC"
exit
esac
modprobe ltq_atm_${soc}

View File

@@ -0,0 +1,29 @@
#!/bin/sh
[ "$DSL_NOTIFICATION_TYPE" = "DSL_STATUS" ] && \
[ "$DSL_TC_LAYER_STATUS" = "EFM" ] && \
! grep -q "ltq_ptm_ar9\|ltq_ptm_ase\|ltq_ptm_danube" /proc/modules || exit 0
logger -p daemon.notice -t "dsl-notify" "Switching to TC-Layer EFM/PTM"
if grep -q "ltq_atm_ar9\|ltq_atm_ase\|ltq_atm_danube" /proc/modules ; then
logger -p daemon.notice -t "dsl-notify" "Loading EFM/PTM driver while ATM driver is loaded is not possible. Reboot is needed."
exit
fi
case "$(strings /proc/device-tree/compatible)" in
*lantiq,ar9*)
soc="ar9"
;;
*lantiq,ase*)
soc="ase"
;;
*lantiq,danube*)
soc="danube"
;;
*)
logger -p daemon.notice -t "dsl-notify" "Unsupported SoC"
exit
esac
modprobe ltq_ptm_${soc}

View File

@@ -0,0 +1,65 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2012 OpenWrt.org
START=97
USE_PROCD=1
dslstat() {
ubus call dsl metrics
}
extra_command "dslstat" "Get DSL status information"
annex_b=10_00_10_00_00_04_00_00
annex_bdmt=10_00_00_00_00_00_00_00
annex_b2=00_00_10_00_00_00_00_00
annex_b2p=00_00_00_00_00_04_00_00
annex_a=05_01_04_00_4C_01_04_00
annex_at1=01_00_00_00_00_00_00_00
annex_alite=00_01_00_00_00_00_00_00
annex_admt=04_00_00_00_00_00_00_00
annex_a2=00_00_04_00_00_00_00_00
annex_a2p=00_00_00_00_00_01_00_00
annex_l=00_00_00_00_0C_00_00_00
annex_m=00_00_00_00_40_00_04_00
annex_m2=00_00_00_00_40_00_00_00
annex_m2p=00_00_00_00_00_00_04_00
annex_j=10_00_10_40_00_04_01_00
service_triggers() {
procd_add_reload_trigger network
}
start_service() {
local annex
local firmware
local xtu
config_load network
config_get annex dsl annex
config_get firmware dsl firmware
eval "xtu=\"\${annex_$annex}\""
[ -z "${firmware}" ] &&
firmware=/lib/firmware/adsl.bin
[ -f "${firmware}" ] || {
echo failed to find $firmware
return 1
}
procd_open_instance
procd_set_param command /sbin/dsl_cpe_control \
-i${xtu} \
-n /sbin/dsl_notify.sh \
-f ${firmware}
procd_close_instance
}
stop_service() {
DSL_NOTIFICATION_TYPE="DSL_INTERFACE_STATUS" \
DSL_INTERFACE_STATUS="DOWN" \
/sbin/dsl_notify.sh
service_stop /sbin/dsl_cpe_control
}

View File

@@ -0,0 +1,65 @@
--- a/src/dsl_cpe_cli_access.c 2016-05-27 12:34:43.612485449 -0700
+++ b/src/dsl_cpe_cli_access.c 2016-05-27 12:45:37.491727862 -0700
@@ -1142,7 +1142,7 @@
if ((ret < 0) && (autobootCtrl.accessCtl.nReturn < DSL_SUCCESS))
{
- DSL_CPE_FPrintf (out, sFailureReturn, autobootCtrl.accessCtl.nReturn);
+ DSL_CPE_FPrintf (out, sFailureReturn, autobootCtrl.accessCtl.nReturn, DSL_CPE_Fd2DevStr(fd));
}
else
{
@@ -1213,7 +1213,7 @@
if ((ret < 0) && (pData.accessCtl.nReturn < DSL_SUCCESS))
{
- DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn);
+ DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn, DSL_CPE_Fd2DevStr(fd));
}
else
{
@@ -1290,7 +1290,7 @@
if ((ret < 0) && (pData.accessCtl.nReturn < DSL_SUCCESS))
{
- DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn);
+ DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn, DSL_CPE_Fd2DevStr(fd));
}
else
{
@@ -1355,7 +1355,7 @@
pCtx, &resourceUsageStatisticsData);
if (ret < 0)
{
- DSL_CPE_FPrintf (out, sFailureReturn, ret);
+ DSL_CPE_FPrintf (out, sFailureReturn, ret, DSL_CPE_Fd2DevStr(fd));
}
else
{
@@ -3084,7 +3084,7 @@
if ((ret < 0) && (pData->accessCtl.nReturn < DSL_SUCCESS))
{
- DSL_CPE_FPrintf (out, sFailureReturn, pData->accessCtl.nReturn);
+ DSL_CPE_FPrintf (out, sFailureReturn, pData->accessCtl.nReturn, DSL_CPE_Fd2DevStr(fd));
}
else
{
@@ -4654,7 +4654,7 @@
if ((ret < 0) && (pData.accessCtl.nReturn < DSL_SUCCESS))
{
- DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn);
+ DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn, DSL_CPE_Fd2DevStr(fd));
}
else
{
@@ -5714,7 +5714,7 @@
if ((ret < 0) && (pData.accessCtl.nReturn < DSL_SUCCESS))
{
- DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn);
+ DSL_CPE_FPrintf (out, sFailureReturn, pData.accessCtl.nReturn, DSL_CPE_Fd2DevStr(fd));
}
else
{

View File

@@ -0,0 +1,23 @@
--- a/configure.in
+++ b/configure.in
@@ -29,6 +29,8 @@ AC_C_VOLATILE
#AC_FUNC_STRTOD
#AC_CHECK_FUNCS([ftime gethostbyname gettimeofday localtime_r memset select socket strchr strerror strstr strtoull])
+AC_SEARCH_LIBS([clock_gettime],[rt])
+
#
# save the configure arguments
#
--- a/src/dsl_cpe_linux.h
+++ b/src/dsl_cpe_linux.h
@@ -45,7 +45,8 @@
#include <arpa/inet.h>
#include <sys/socket.h> /* socket */
#include <sys/sem.h> /* semget */
-#include <semaphore.h> /* sem_t */
+#include <semaphore.h> /* sem_t */
+#include <limits.h>
#ifdef DSL_DEBUG_TOOL_INTERFACE
#include <sys/socket.h>

View File

@@ -0,0 +1,42 @@
From 9d4f86ba2cf10304303011f4f5628fa68dc77624 Mon Sep 17 00:00:00 2001
From: Mathias Kresin <dev@kresin.me>
Date: Mon, 16 Oct 2017 21:08:26 +0200
Subject: ltq-adsl-app: add more script notifications
Backport HANDSHAKE and TRAINING notification from ltq-vdsl-app. It
unifies the dsl led blinking pattern accross all subtargets and allows
to get the current line status from the dsl led.
Signed-off-by: Mathias Kresin <dev@kresin.me>
---
.../100-add-more-script-notifications.patch | 27 ++++++++++++++++++++++
1 file changed, 27 insertions(+)
create mode 100644 package/network/config/ltq-adsl-app/patches/100-add-more-script-notifications.patch
--- a/src/dsl_cpe_control.c
+++ b/src/dsl_cpe_control.c
@@ -3273,7 +3273,23 @@ DSL_CPE_STATIC DSL_int_t DSL_CPE_Event_S
#ifdef INCLUDE_SCRIPT_NOTIFICATION
if (g_sRcScript != DSL_NULL)
{
- if ( (nLineState == DSL_LINESTATE_SHOWTIME_TC_SYNC) &&
+ if ( (nLineState == DSL_LINESTATE_HANDSHAKE) &&
+ (g_nPrevLineState[nDevice] != DSL_LINESTATE_HANDSHAKE) )
+ {
+ if (DSL_CPE_SetEnv("DSL_INTERFACE_STATUS", "HANDSHAKE") == DSL_SUCCESS)
+ {
+ bExec = DSL_TRUE;
+ }
+ }
+ else if ( (nLineState == DSL_LINESTATE_FULL_INIT) &&
+ (g_nPrevLineState[nDevice] != DSL_LINESTATE_FULL_INIT) )
+ {
+ if (DSL_CPE_SetEnv("DSL_INTERFACE_STATUS", "TRAINING") == DSL_SUCCESS)
+ {
+ bExec = DSL_TRUE;
+ }
+ }
+ else if ( (nLineState == DSL_LINESTATE_SHOWTIME_TC_SYNC) &&
(g_nPrevLineState[nDevice] != DSL_LINESTATE_SHOWTIME_TC_SYNC) )
{
if (DSL_CPE_SetEnv("DSL_INTERFACE_STATUS", "UP") == DSL_SUCCESS)

View File

@@ -0,0 +1,50 @@
--- a/src/dsl_cpe_control.c
+++ b/src/dsl_cpe_control.c
@@ -139,6 +139,9 @@ extern DSL_Error_t DSL_CPE_Pipe_StaticRe
#endif /* INCLUDE_DSL_RESOURCE_STATISTICS*/
#endif
+extern void ubus_init();
+extern void ubus_deinit();
+
DSL_char_t *g_sFirmwareName1 = DSL_NULL;
DSL_char_t *g_sFirmwareName2 = DSL_NULL;
#ifdef INCLUDE_SCRIPT_NOTIFICATION
@@ -5343,6 +5346,8 @@ DSL_int_t dsl_cpe_daemon (
signal (SIGINT, DSL_CPE_TerminationHandler);
#endif /* RTEMS*/
+ ubus_init();
+
/* Open DSL_CPE_MAX_DEVICE_NUMBER devices*/
for (nDevice = 0; nDevice < DSL_CPE_MAX_DEVICE_NUMBER; nDevice++)
{
@@ -5738,6 +5743,7 @@ DSL_int_t dsl_cpe_daemon (
#endif /* INCLUDE_DSL_CPE_CLI_SUPPORT */
DSL_CPE_CONTROL_EXIT:
+ ubus_deinit();
#ifdef INCLUDE_DSL_BONDING
DSL_CPE_BND_Stop((DSL_CPE_BND_Context_t*)pCtrlCtx->pBnd);
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,7 +11,7 @@ else
dsl_cpe_control_common_ldflags =
endif
-dsl_cpe_control_LDADD = -lpthread
+dsl_cpe_control_LDADD = -lpthread -lubox -lubus
if INCLUDE_DSL_CPE_SOAP_SUPPORT
dsl_cpe_control_LDADD += -lm
@@ -70,7 +70,8 @@ dsl_cpe_control_SOURCES = \
dsl_cpe_control.c \
dsl_cpe_init_cfg.c \
dsl_cpe_linux.c \
- dsl_cpe_debug.c
+ dsl_cpe_debug.c \
+ dsl_cpe_ubus.c
dsl_cpe_control_SOURCES += \
$(dsl_cpe_control_dti_sources)

View File

@@ -0,0 +1,82 @@
# Copyright (C) 2010 OpenWrt.org
# Copyright (C) 2015-2016 Lantiq Beteiligungs GmbH & Co KG.
#
# 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:=ltq-vdsl-app
PKG_VERSION:=4.17.18.6
PKG_RELEASE:=9
PKG_BASE_NAME:=dsl_cpe_control
PKG_SOURCE:=$(PKG_BASE_NAME)_vrx-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=@OPENWRT
PKG_HASH:=da8bb929526a61aea0e153ef524331fcd472a1ebbc6d88ca017735a4f82ece02
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_BASE_NAME)-$(PKG_VERSION)
PKG_LICENSE:=BSD-2-Clause
PKG_BUILD_DEPENDS:=ltq-vdsl
PKG_FLAGS:=nonshared
PKG_FIXUP:=autoreconf
include $(INCLUDE_DIR)/package.mk
define Package/ltq-vdsl-app
SECTION:=net
CATEGORY:=Network
TITLE:=Lantiq VDSL userland tool
URL:=http://www.lantiq.com/
DEPENDS:=@TARGET_lantiq_xrx200 +libpthread +librt +ltq-dsl-base +libubox +libubus
endef
define Package/ltq-vdsl-app/description
Userland tool needed to control Lantiq VDSL CPE
endef
# ltq-vdsl-app uses a header provided by the MEI driver which has some
# conditionals.
#
# Define them here with the default values they would get in the MEI driver,
# have the same view on both sides.
#
# If you change them, you need to change them for the ltq-vdsl-app as well
VDSL_APP_CFLAGS = \
-DMAX_CLI_PIPES=1 \
-DMEI_SUPPORT_DEBUG_STREAMS=1 \
-DMEI_SUPPORT_OPTIMIZED_FW_DL=1
CONFIGURE_ARGS += \
--enable-vrx \
--enable-vrx-device=vr9 \
--enable-driver-include="-I$(STAGING_DIR)/usr/include/drv_vdsl_cpe_api" \
--enable-device-driver-include="-I$(STAGING_DIR)/usr/include/vdsl/" \
--enable-ifxos \
--enable-ifxos-include="-I$(STAGING_DIR)/usr/include/ifxos" \
--enable-ifxos-library="-I$(STAGING_DIR)/usr/lib" \
--enable-add-appl-cflags="$(VDSL_APP_CFLAGS)" \
--enable-debug \
--disable-dti \
--with-channels-per-line="1"
CONFIGURE_ARGS += \
--enable-model=full \
--enable-dsl-ceoc=no
#CONFIGURE_ARGS += --enable-model=lite
#CONFIGURE_ARGS += --enable-model=footprint
#CONFIGURE_ARGS += --enable-model=typical
#CONFIGURE_ARGS += --enable-model=debug
define Package/ltq-vdsl-app/install
$(INSTALL_DIR) $(1)/etc/init.d $(1)/sbin $(1)/etc/hotplug.d/dsl
$(INSTALL_BIN) ./files/dsl_control $(1)/etc/init.d/
$(INSTALL_BIN) ./files/10_atm.sh $(1)/etc/hotplug.d/dsl
$(INSTALL_BIN) ./files/10_ptm.sh $(1)/etc/hotplug.d/dsl
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/dsl_cpe_control $(1)/sbin/vdsl_cpe_control
$(INSTALL_BIN) ./files/dsl_cpe_pipe.sh $(1)/sbin/
endef
$(eval $(call BuildPackage,ltq-vdsl-app))

View File

@@ -0,0 +1,14 @@
#!/bin/sh
[ "$DSL_NOTIFICATION_TYPE" = "DSL_STATUS" ] && \
[ "$DSL_TC_LAYER_STATUS" = "ATM" ] && \
! grep -q "ltq_atm_vr9" /proc/modules || exit 0
logger -p daemon.notice -t "dsl-notify" "Switching to TC-Layer ATM"
if grep -q "ltq_ptm_vr9" /proc/modules ; then
logger -p daemon.notice -t "dsl-notify" "Loading ATM driver while EFM/PTM driver is loaded is not possible. Reboot is needed."
exit
fi
modprobe ltq_atm_vr9

View File

@@ -0,0 +1,14 @@
#!/bin/sh
[ "$DSL_NOTIFICATION_TYPE" = "DSL_STATUS" ] && \
[ "$DSL_TC_LAYER_STATUS" = "EFM" ] && \
! grep -q "ltq_ptm_vr9" /proc/modules || exit 0
logger -p daemon.notice -t "dsl-notify" "Switching to TC-Layer EFM/PTM"
if grep -q "ltq_atm_vr9" /proc/modules ; then
logger -p daemon.notice -t "dsl-notify" "Loading EFM/PTM driver while ATM driver is loaded is not possible. Reboot is needed."
exit
fi
modprobe ltq_ptm_vr9

View File

@@ -0,0 +1,314 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2012 OpenWrt.org
START=97
USE_PROCD=1
dslstat() {
ubus call dsl metrics
}
extra_command "dslstat" "Get DSL status information"
#
# ITU-T G.997.1 (06/2012) - Section 7.3.1.1.1 (xTU transmission system enabling (XTSE))
# ITU-T G.997.1 Amendment 2 (04/2013) - Section 2.1 - (Vectoring mode enable (VECTORMODE_ENABLE))
#
# G.992.1 Annex A
# G.992.2 Annex A
# G.992.3 Annex A / L-US1 / L_US-2 / M
# G.992.5 Annex A / M
# G.993.2 Annex A/B/C
# G.993.5 Annex A/B/C
xtse_xdsl_a="05_01_04_00_4C_01_04_07"
# G.992.1 Annex B
# G.992.3 Annex B
# G.992.5 Annex B
# G.993.2 Annex A/B/C
# G.993.5 Annex A/B/C
xtse_xdsl_b="10_00_10_00_00_04_00_07"
# G.992.1 Annex B
# G.992.3 Annex B
# G.992.3 Annex J
# G.992.5 Annex B
# G.992.5 Annex J
# G.993.2 Annex A/B/C
# G.993.5 Annex A/B/C
xtse_xdsl_j="10_00_10_40_00_04_01_07"
# G.992.1 Annex B
xtse_xdsl_bdmt="10_00_00_00_00_00_00_00"
# G.992.3 Annex B
xtse_xdsl_b2="00_00_10_00_00_00_00_00"
# G.992.5 Annex B
xtse_xdsl_b2p="00_00_00_00_00_04_00_00"
# ANSI T1.413
xtse_xdsl_at1="01_00_00_00_00_00_00_00"
# G.992.2 Annex A
xtse_xdsl_alite="00_01_00_00_00_00_00_00"
# G.992.1 Annex A
xtse_xdsl_admt="04_00_00_00_00_00_00_00"
# G.992.3 Annex A
xtse_xdsl_a2="00_00_04_00_00_00_00_00"
# G.992.5 Annex A
xtse_xdsl_a2p="00_00_00_00_00_01_00_00"
# G.992.3 Annex L
xtse_xdsl_l="00_00_00_00_0C_00_00_00"
# G.992.3 Annex M
# G.992.5 Annex M
xtse_xdsl_m="00_00_00_00_40_00_04_00"
# G.992.3 Annex M
xtse_xdsl_m2="00_00_00_00_40_00_00_00"
# G.992.5 Annex M
xtse_xdsl_m2p="00_00_00_00_00_00_04_00"
#
# ITU-T G.994.1 (06/2012) - Table 2 (Mandatory carrier sets)
#
# A43
tone_adsl_a="0x142" # A43C + J43 + A43
tone_vdsl_a="0x142" # A43C + J43 + A43
# A43 + V43
tone_adsl_av="0x142" # A43C + J43 + A43
tone_vdsl_av="0x146" # A43C + J43 + A43 + V43
# B43
tone_adsl_b="0x81" # B43 + B43c
tone_vdsl_b="0x1" # B43
# B43 + V43
tone_adsl_bv="0x81" # B43 + B43c
tone_vdsl_bv="0x5" # B43 + V43
# create ADSL autoboot script. Used for SNR margin tweak
autoboot_script() {
echo "[WaitForConfiguration]={
locs 0 $1
}
[WaitForLinkActivate]={
}
[WaitForRestart]={
}
[Common]={
}" > /tmp/dsl.scr
}
lowlevel_cfg() {
echo "# VRX Low Level Configuration File
#
# Parameters must be separated by tabs or spaces.
# Empty lines and comments will be ignored.
#
# nFilter
#
# NA = -1
# OFF = 0
# ISDN = 1
# POTS = 2
# POTS_2 = 3
# POTS_3 = 4
#
# (dec)
-1
# nHsToneGroupMode nHsToneGroup_A nHsToneGroup_V nHsToneGroup_AV
#
# NA = -1 NA = -1 see see
# AUTO = 0 VDSL2_B43 = 0x0001 nHsToneGroup_A nHsToneGroup_A
# MANUAL = 1 VDSL2_A43 = 0x0002
# VDSL2_V43 = 0x0004
# VDSL1_V43P = 0x0008
# VDSL1_V43I = 0x0010
# ADSL1_C43 = 0x0020
# ADSL2_J43 = 0x0040
# ADSL2_B43C = 0x0080
# ADSL2_A43C = 0x0100
#
# (dec) (hex) (hex) (hex)
1 $1 $2 0x0
# nBaseAddr nIrqNum
#
# (hex) (dec)
0x1e116000 63
# nUtopiaPhyAdr nUtopiaBusWidth nPosPhyParity
# default(16b) = 0 NA = -1
# 8-bit = 1 ODD = 0
# 16-bit = 2
#
#
# (hex) (dec) (dec)
0xFF 0 0
# bNtrEnable
#
# (dec)
0" > /tmp/lowlevel.cfg
}
service_triggers() {
procd_add_reload_trigger network
}
start_service() {
local annex
local firmware
local tone
local tone_adsl
local tone_vdsl
local xtse
local xfer_mode
local line_mode
local tc_layer
local mode
local lowlevel
local snr
config_load network
config_get tone dsl tone
config_get annex dsl annex
config_get firmware dsl firmware
config_get xfer_mode dsl xfer_mode
config_get line_mode dsl line_mode
config_get snr dsl ds_snr_offset
eval "xtse=\"\${xtse_xdsl_$annex}\""
case "${xfer_mode}" in
atm)
tc_layer="-T1:0x1:0x1_1:0x1:0x1"
;;
ptm)
tc_layer="-T2:0x1:0x1_2:0x1:0x1"
;;
esac
case "${line_mode}" in
adsl)
mode="-M1"
# mask out VDSL bits when ADSL is requested
xtse="${xtse%_*}_00"
;;
vdsl)
mode="-M2"
# mask out ADSL bits when VDSL is requested
xtse="00_00_00_00_00_00_00_${xtse##*_}"
;;
esac
local annexgpio="/sys/class/gpio/annex"
if [ -d "${annexgpio}a" ] && [ -d "${annexgpio}b" ]; then
case "${annex}" in
a*|l*|m*)
echo 1 > "${annexgpio}a/value"
echo 0 > "${annexgpio}b/value"
;;
b*|j*)
echo 0 > "${annexgpio}a/value"
echo 1 > "${annexgpio}b/value"
;;
esac
fi
if [ -z "${firmware}" ]; then
# search for the firmware provided by dsl-vrx200-firmware-xdsl-*
if grep -qE "system type.*: (VR9|xRX200)" /proc/cpuinfo; then
case "${annex}" in
a*|l*|m*)
if [ -f "/lib/firmware/lantiq-vrx200-a.bin" ]; then
firmware="/lib/firmware/lantiq-vrx200-a.bin"
elif [ -f "/tmp/lantiq-vrx200-a.bin" ]; then
firmware="/tmp/lantiq-vrx200-a.bin"
elif [ -f "/lib/firmware/lantiq-vrx200-b.bin" ] && [ -f "/lib/firmware/lantiq-vrx200-b-to-a.bspatch" ]; then
bspatch /lib/firmware/lantiq-vrx200-b.bin \
/tmp/lantiq-vrx200-a.bin \
/lib/firmware/lantiq-vrx200-b-to-a.bspatch
firmware="/tmp/lantiq-vrx200-a.bin"
else
echo "firmware for annex a not found"
return 1
fi
;;
b*|j*)
if [ -f "/lib/firmware/vr9_dsl_fw_annex_b.bin" ]; then
firmware="/lib/firmware/vr9_dsl_fw_annex_b.bin"
elif [ -f "/lib/firmware/lantiq-vrx200-b.bin" ]; then
firmware="/lib/firmware/lantiq-vrx200-b.bin"
elif [ -f "/tmp/lantiq-vrx200-b.bin" ]; then
firmware="/tmp/lantiq-vrx200-b.bin"
elif [ -f "/lib/firmware/lantiq-vrx200-a.bin" ] && [ -f "/lib/firmware/lantiq-vrx200-a-to-b.bspatch" ]; then
bspatch /lib/firmware/lantiq-vrx200-a.bin \
/tmp/lantiq-vrx200-b.bin \
/lib/firmware/lantiq-vrx200-a-to-b.bspatch
firmware="/tmp/lantiq-vrx200-b.bin"
else
echo "firmware for annex b not found"
return 1
fi
;;
*)
echo "annex type not supported use a or b"
return 1
;;
esac
fi
fi
[ -z "${firmware}" ] && firmware=/lib/firmware/vdsl.bin
[ -f "${firmware}" ] || {
echo failed to find $firmware
return 1
}
eval "tone_adsl=\"\${tone_adsl_$tone}\""
eval "tone_vdsl=\"\${tone_vdsl_$tone}\""
[ -n "${tone_adsl}" ] && [ -n "${tone_vdsl}" ] && {
lowlevel_cfg "${tone_adsl}" "${tone_vdsl}"
lowlevel="-l /tmp/lowlevel.cfg"
}
[ -z "${snr}" ] || {
# for SNR offset setting
autoboot_script "$snr"
autoboot="-a /tmp/dsl.scr -A /tmp/dsl.scr"
}
procd_open_instance
procd_set_param command /sbin/vdsl_cpe_control \
-i$xtse \
-n /sbin/dsl_notify.sh \
-f ${firmware} \
$lowlevel \
${mode} \
${tc_layer} \
$autoboot
procd_close_instance
}
stop_service() {
DSL_NOTIFICATION_TYPE="DSL_INTERFACE_STATUS" \
DSL_INTERFACE_STATUS="DOWN" \
/sbin/dsl_notify.sh
}

View File

@@ -0,0 +1,18 @@
#!/bin/sh
pipe_no=0
# use specified pipe no
case "$1" in
0|1|2)
pipe_no=$1; shift; ;;
esac
#echo "Call dsl_pipe with $*"
lock /var/lock/dsl_pipe
echo $* > /tmp/pipe/dsl_cpe${pipe_no}_cmd
result=$(cat /tmp/pipe/dsl_cpe${pipe_no}_ack)
lock -u /var/lock/dsl_pipe
echo "$result"

View File

@@ -0,0 +1,22 @@
--- a/src/dsl_cpe_init_cfg.c
+++ b/src/dsl_cpe_init_cfg.c
@@ -38,7 +38,7 @@ DSL_InitData_t gInitCfgData =
DSL_DEV_HS_TONE_GROUP_CLEANED, \
DSL_DEV_HS_TONE_GROUP_CLEANED, \
DSL_DEV_HS_TONE_GROUP_CLEANED, \
- 0x1E116000, 0x37, -1),
+ 0x1E116000, 0x3f, -1),
DSL_CPE_SIC_SET(DSL_TC_ATM, DSL_EMF_TC_CLEANED, DSL_EMF_TC_CLEANED, DSL_SYSTEMIF_MII, \
DSL_TC_EFM, DSL_EMF_TC_CLEANED, DSL_EMF_TC_CLEANED, DSL_SYSTEMIF_MII),
DSL_CPE_MAC_CFG_SET(DSL_EFM_SPEED_100, DSL_EFM_DUPLEX_FULL, DSL_EFM_FLOWCTRL_ON, DSL_EFM_AUTONEG_OFF, \
--- a/src/dsl_cpe_control.c
+++ b/src/dsl_cpe_control.c
@@ -6761,7 +6761,7 @@ DSL_int_t dsl_cpe_daemon (
for (nDevice = 0; nDevice < DSL_CPE_MAX_DSL_ENTITIES; nDevice++)
{
#if defined(INCLUDE_DSL_CPE_API_VRX)
- sprintf (device, "%s/%d", DSL_CPE_DEVICE_NAME, nDevice);
+ sprintf (device, "%s%d", DSL_CPE_DEVICE_NAME, nDevice);
#else
sprintf (device, "%s", DSL_CPE_DEVICE_NAME);
#endif /* defined(INCLUDE_DSL_CPE_API_VRX)*/

View File

@@ -0,0 +1,10 @@
--- a/src/dsl_cpe_control.c
+++ b/src/dsl_cpe_control.c
@@ -11,6 +11,7 @@
/*
Includes
*/
+#include <limits.h>
#include "dsl_cpe_control.h"
#include "dsl_cpe_cli.h"
#include "dsl_cpe_cli_console.h"

View File

@@ -0,0 +1,11 @@
--- a/src/dsl_cpe_init_cfg.c
+++ b/src/dsl_cpe_init_cfg.c
@@ -27,7 +27,7 @@ DSL_InitData_t gInitCfgData =
DSL_CPE_FW2_SET(DSL_NULL, 0x0),
DSL_CPE_XTU_SET(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7),
DSL_CPE_LINE_INV_NE_SET(DSL_NULL),
- DSL_CPE_AUTOBOOT_CTRL_SET(DSL_AUTOBOOT_CTRL_STOP),
+ DSL_CPE_AUTOBOOT_CTRL_SET(DSL_AUTOBOOT_CTRL_START),
DSL_CPE_AUTOBOOT_CFG_SET(DSL_FALSE, DSL_FALSE, DSL_FALSE),
DSL_CPE_TEST_MODE_CTRL_SET(DSL_TESTMODE_DISABLE),
DSL_CPE_LINE_ACTIVATE_CTRL_SET(DSL_G997_INHIBIT_LDSF, DSL_G997_INHIBIT_ACSF, DSL_G997_NORMAL_STARTUP),

View File

@@ -0,0 +1,19 @@
--- a/src/dsl_cpe_control.c
+++ b/src/dsl_cpe_control.c
@@ -6504,7 +6504,7 @@ DSL_CPE_STATIC void DSL_CPE_Termination
/* ignore the signal, we'll handle by ourself */
signal (sig, SIG_IGN);
- if (sig == SIGINT)
+ if (sig == SIGINT || sig == SIGTERM)
{
DSL_CCA_DEBUG(DSL_CCA_DBG_MSG, (DSL_CPE_PREFIX "terminated" DSL_CPE_CRLF));
DSL_CPE_Termination ();
@@ -6756,6 +6756,7 @@ DSL_int_t dsl_cpe_daemon (
#ifndef RTEMS
signal (SIGINT, DSL_CPE_TerminationHandler);
+ signal (SIGTERM, DSL_CPE_TerminationHandler);
#endif /* RTEMS*/
/* Open DSL_CPE_MAX_DSL_ENTITIES devices*/

View File

@@ -0,0 +1,50 @@
--- a/src/dsl_cpe_control.c
+++ b/src/dsl_cpe_control.c
@@ -177,6 +177,9 @@ extern DSL_Error_t DSL_CPE_Pipe_StaticRe
#endif /* INCLUDE_DSL_RESOURCE_STATISTICS*/
#endif
+extern void ubus_init();
+extern void ubus_deinit();
+
DSL_char_t *g_sFirmwareName1 = DSL_NULL;
DSL_FirmwareFeatures_t g_nFwFeatures1 = {DSL_FW_XDSLMODE_CLEANED, DSL_FW_XDSLFEATURE_CLEANED,
DSL_FW_XDSLFEATURE_CLEANED};
@@ -6759,6 +6762,8 @@ DSL_int_t dsl_cpe_daemon (
signal (SIGTERM, DSL_CPE_TerminationHandler);
#endif /* RTEMS*/
+ ubus_init();
+
/* Open DSL_CPE_MAX_DSL_ENTITIES devices*/
for (nDevice = 0; nDevice < DSL_CPE_MAX_DSL_ENTITIES; nDevice++)
{
@@ -7213,6 +7218,7 @@ DSL_int_t dsl_cpe_daemon (
#endif /* INCLUDE_DSL_CPE_CLI_SUPPORT */
DSL_CPE_CONTROL_EXIT:
+ ubus_deinit();
#ifdef INCLUDE_DSL_BONDING
DSL_CPE_BND_Stop((DSL_CPE_BND_Context_t*)pCtrlCtx->pBnd);
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,7 +11,7 @@ else
dsl_cpe_control_common_ldflags =
endif
-dsl_cpe_control_LDADD = -lpthread -lrt
+dsl_cpe_control_LDADD = -lpthread -lrt -lubox -lubus
if INCLUDE_DSL_CPE_DTI_SUPPORT
dsl_cpe_control_LDADD += -ldti_agent
@@ -66,7 +66,8 @@ dsl_cpe_control_SOURCES = \
dsl_cpe_control.c \
dsl_cpe_init_cfg.c \
dsl_cpe_linux.c \
- dsl_cpe_debug.c
+ dsl_cpe_debug.c \
+ dsl_cpe_ubus.c
dsl_cpe_control_SOURCES += \
$(dsl_cpe_control_dti_sources)

View File

@@ -0,0 +1,856 @@
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (C) 2020 Andre Heider <a.heider@gmail.com>
*/
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <libubus.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "dsl_cpe_control.h"
#include <drv_dsl_cpe_api_ioctl.h>
#ifdef INCLUDE_DSL_CPE_API_VRX
#include <drv_mei_cpe_interface.h>
#endif
#define U16(v1, v2) ( \
((uint16_t)(v1) << 8) | \
((uint16_t)(v2)))
#define U32(v1, v2, v3, v4) ( \
((uint32_t)(v1) << 24) | \
((uint32_t)(v2) << 16) | \
((uint32_t)(v3) << 8) | \
((uint32_t)(v4)))
#define STR_CASE(id, text) \
case id: \
str = text; \
break;
#define STR_CASE_MAP(id, text, number) \
case id: \
str = text; \
map = number; \
break;
#define IOCTL(type, request) \
type out; \
memset(&out, 0, sizeof(type)); \
if (ioctl(fd, request, &out)) \
return;
#define IOCTL_DIR(type, request, dir) \
type out; \
memset(&out, 0, sizeof(type)); \
out.nDirection = dir; \
if (ioctl(fd, request, &out)) \
return;
#define IOCTL_DIR_DELT(type, request, dir, delt) \
type out; \
memset(&out, 0, sizeof(type)); \
out.nDirection = dir; \
out.nDeltDataType = delt; \
if (ioctl(fd, request, &out)) \
return;
typedef enum {
ANNEX_UNKNOWN = 0,
ANNEX_A,
ANNEX_B,
ANNEX_C,
ANNEX_I,
ANNEX_J,
ANNEX_L,
ANNEX_M,
} annex_t;
typedef enum {
STD_UNKNOWN = 0,
STD_T1_413,
STD_TS_101_388,
STD_G_992_1,
STD_G_992_2,
STD_G_992_3,
STD_G_992_4,
STD_G_992_5,
STD_G_993_1,
STD_G_993_2,
} standard_t;
typedef enum {
VECTOR_UNKNOWN = 0,
VECTOR_OFF,
VECTOR_ON_DS,
VECTOR_ON_DS_US,
} vector_t;
typedef enum {
PROFILE_UNKNOWN = 0,
PROFILE_8A,
PROFILE_8B,
PROFILE_8C,
PROFILE_8D,
PROFILE_12A,
PROFILE_12B,
PROFILE_17A,
PROFILE_30A,
PROFILE_35B,
} profile_t;
/* These values are exported via ubus and backwards compability
* needs to be kept!
*/
enum {
LSTATE_MAP_UNKNOWN = -1,
LSTATE_MAP_NOT_INITIALIZED,
LSTATE_MAP_EXCEPTION,
LSTATE_MAP_IDLE,
LSTATE_MAP_SILENT,
LSTATE_MAP_HANDSHAKE,
LSTATE_MAP_FULL_INIT,
LSTATE_MAP_SHOWTIME_NO_SYNC,
LSTATE_MAP_SHOWTIME_TC_SYNC,
LSTATE_MAP_RESYNC,
};
/* These values are exported via ubus and backwards compability
* needs to be kept!
*/
enum {
PSTATE_MAP_UNKNOWN = -2,
PSTATE_MAP_NA,
PSTATE_MAP_L0,
PSTATE_MAP_L1,
PSTATE_MAP_L2,
PSTATE_MAP_L3,
};
static DSL_CPE_ThreadCtrl_t thread;
static struct ubus_context *ctx;
static struct blob_buf b;
static inline void m_double(const char *id, double value) {
blobmsg_add_double(&b, id, value);
}
static inline void m_bool(const char *id, bool value) {
blobmsg_add_u8(&b, id, value);
}
static inline void m_u32(const char *id, uint32_t value) {
blobmsg_add_u32(&b, id, value);
}
static inline void m_str(const char *id, const char *value) {
blobmsg_add_string(&b, id, value);
}
static inline void m_db(const char *id, int value) {
m_double(id, (double)value / 10);
}
static inline void m_array(const char *id, const uint8_t *value, uint8_t len) {
void *c = blobmsg_open_array(&b, id);
for (uint8_t i = 0; i < len; ++i)
blobmsg_add_u16(&b, "", value[i]);
blobmsg_close_array(&b, c);
}
static void m_vendor(const char *id, const uint8_t *value) {
// ITU-T T.35: U.S.
if (U16(value[0], value[1]) != 0xb500)
return;
const char *str = NULL;
switch (U32(value[2], value[3], value[4], value[5])) {
STR_CASE(0x414C4342, "Alcatel")
STR_CASE(0x414E4456, "Analog Devices")
STR_CASE(0x4244434D, "Broadcom")
STR_CASE(0x43454E54, "Centillium")
STR_CASE(0x4753504E, "Globespan")
STR_CASE(0x494B4E53, "Ikanos")
STR_CASE(0x4946544E, "Infineon")
STR_CASE(0x54535443, "Texas Instruments")
STR_CASE(0x544D4D42, "Thomson MultiMedia Broadband")
STR_CASE(0x5443544E, "Trend Chip Technologies")
STR_CASE(0x53544D49, "ST Micro")
};
if (!str)
return;
if ((value[6] == 0) && (value[7] == 0)) {
m_str(id, str);
return;
}
char buf[64];
sprintf(buf, "%s %d.%d", str, value[6], value[7]);
m_str(id, buf);
return;
}
annex_t get_annex(const uint8_t *xtse) {
if ((xtse[0] & XTSE_1_01_A_T1_413) ||
(xtse[0] & XTSE_1_03_A_1_NO) ||
(xtse[0] & XTSE_1_04_A_1_O) ||
(xtse[1] & XTSE_2_01_A_2_NO) ||
(xtse[2] & XTSE_3_03_A_3_NO) ||
(xtse[2] & XTSE_3_04_A_3_O) ||
(xtse[3] & XTSE_4_01_A_4_NO) ||
(xtse[3] & XTSE_4_02_A_4_O) ||
(xtse[5] & XTSE_6_01_A_5_NO) ||
(xtse[5] & XTSE_6_02_A_5_O) ||
(xtse[7] & XTSE_8_01_A))
return ANNEX_A;
if ((xtse[0] & XTSE_1_05_B_1_NO) ||
(xtse[0] & XTSE_1_06_B_1_O) ||
(xtse[1] & XTSE_2_02_B_2_O) ||
(xtse[2] & XTSE_3_05_B_3_NO) ||
(xtse[2] & XTSE_3_06_B_3_O) ||
(xtse[5] & XTSE_6_03_B_5_NO) ||
(xtse[5] & XTSE_6_04_B_5_O) ||
(xtse[7] & XTSE_8_02_B))
return ANNEX_B;
if ((xtse[0] & XTSE_1_02_C_TS_101388) ||
(xtse[0] & XTSE_1_07_C_1_NO) ||
(xtse[0] & XTSE_1_08_C_1_O) ||
(xtse[1] & XTSE_2_03_C_2_NO) ||
(xtse[1] & XTSE_2_04_C_2_O) ||
(xtse[7] & XTSE_8_03_C))
return ANNEX_C;
if ((xtse[3] & XTSE_4_05_I_3_NO) ||
(xtse[3] & XTSE_4_06_I_3_O) ||
(xtse[4] & XTSE_5_01_I_4_NO) ||
(xtse[4] & XTSE_5_02_I_4_O) ||
(xtse[5] & XTSE_6_07_I_5_NO) ||
(xtse[5] & XTSE_6_08_I_5_O))
return ANNEX_I;
if ((xtse[3] & XTSE_4_07_J_3_NO) ||
(xtse[3] & XTSE_4_08_J_3_O) ||
(xtse[6] & XTSE_7_01_J_5_NO) ||
(xtse[6] & XTSE_7_02_J_5_O))
return ANNEX_J;
if ((xtse[4] & XTSE_5_03_L_3_NO) ||
(xtse[4] & XTSE_5_04_L_3_NO) ||
(xtse[4] & XTSE_5_05_L_3_O) ||
(xtse[4] & XTSE_5_06_L_3_O))
return ANNEX_L;
if ((xtse[4] & XTSE_5_07_M_3_NO) ||
(xtse[4] & XTSE_5_08_M_3_O) ||
(xtse[6] & XTSE_7_03_M_5_NO) ||
(xtse[6] & XTSE_7_04_M_5_O))
return ANNEX_M;
return ANNEX_UNKNOWN;
}
static standard_t get_standard(const uint8_t *xtse) {
if (xtse[0] & XTSE_1_01_A_T1_413)
return STD_T1_413;
if (xtse[0] & XTSE_1_02_C_TS_101388)
return STD_TS_101_388;
if ((xtse[0] & XTSE_1_03_A_1_NO) ||
(xtse[0] & XTSE_1_04_A_1_O) ||
(xtse[0] & XTSE_1_05_B_1_NO) ||
(xtse[0] & XTSE_1_06_B_1_O) ||
(xtse[0] & XTSE_1_07_C_1_NO) ||
(xtse[0] & XTSE_1_08_C_1_O))
return STD_G_992_1;
if ((xtse[1] & XTSE_2_01_A_2_NO) ||
(xtse[1] & XTSE_2_02_B_2_O) ||
(xtse[1] & XTSE_2_03_C_2_NO) ||
(xtse[1] & XTSE_2_04_C_2_O))
return STD_G_992_2;
if ((xtse[2] & XTSE_3_03_A_3_NO) ||
(xtse[2] & XTSE_3_04_A_3_O) ||
(xtse[2] & XTSE_3_05_B_3_NO) ||
(xtse[2] & XTSE_3_06_B_3_O) ||
(xtse[3] & XTSE_4_05_I_3_NO) ||
(xtse[3] & XTSE_4_06_I_3_O) ||
(xtse[3] & XTSE_4_07_J_3_NO) ||
(xtse[3] & XTSE_4_08_J_3_O) ||
(xtse[4] & XTSE_5_03_L_3_NO) ||
(xtse[4] & XTSE_5_04_L_3_NO) ||
(xtse[4] & XTSE_5_05_L_3_O) ||
(xtse[4] & XTSE_5_06_L_3_O) ||
(xtse[4] & XTSE_5_07_M_3_NO) ||
(xtse[4] & XTSE_5_08_M_3_O))
return STD_G_992_3;
if ((xtse[3] & XTSE_4_01_A_4_NO) ||
(xtse[3] & XTSE_4_02_A_4_O) ||
(xtse[4] & XTSE_5_01_I_4_NO) ||
(xtse[4] & XTSE_5_02_I_4_O))
return STD_G_992_4;
if ((xtse[5] & XTSE_6_01_A_5_NO) ||
(xtse[5] & XTSE_6_02_A_5_O) ||
(xtse[5] & XTSE_6_03_B_5_NO) ||
(xtse[5] & XTSE_6_04_B_5_O) ||
(xtse[5] & XTSE_6_07_I_5_NO) ||
(xtse[5] & XTSE_6_08_I_5_O) ||
(xtse[6] & XTSE_7_01_J_5_NO) ||
(xtse[6] & XTSE_7_02_J_5_O) ||
(xtse[6] & XTSE_7_03_M_5_NO) ||
(xtse[6] & XTSE_7_04_M_5_O))
return STD_G_992_5;
if (xtse[7] & XTSE_8_08)
return STD_G_993_1;
if ((xtse[7] & XTSE_8_01_A) ||
(xtse[7] & XTSE_8_02_B) ||
(xtse[7] & XTSE_8_03_C))
return STD_G_993_2;
return STD_UNKNOWN;
}
static void version_information(int fd) {
IOCTL(DSL_VersionInformation_t, DSL_FIO_VERSION_INFORMATION_GET)
m_str("api_version", out.data.DSL_DriverVersionApi);
m_str("firmware_version", out.data.DSL_ChipSetFWVersion);
m_str("chipset", out.data.DSL_ChipSetType);
m_str("driver_version", out.data.DSL_DriverVersionMeiBsp);
}
static void line_state(int fd) {
IOCTL(DSL_LineState_t, DSL_FIO_LINE_STATE_GET)
int map = LSTATE_MAP_UNKNOWN;
const char *str;
switch (out.data.nLineState) {
STR_CASE_MAP(DSL_LINESTATE_NOT_INITIALIZED, "Not initialized", LSTATE_MAP_NOT_INITIALIZED)
STR_CASE_MAP(DSL_LINESTATE_EXCEPTION, "Exception", LSTATE_MAP_EXCEPTION)
STR_CASE(DSL_LINESTATE_NOT_UPDATED, "Not updated")
STR_CASE(DSL_LINESTATE_IDLE_REQUEST, "Idle request")
STR_CASE_MAP(DSL_LINESTATE_IDLE, "Idle", LSTATE_MAP_IDLE)
STR_CASE(DSL_LINESTATE_SILENT_REQUEST, "Silent request")
STR_CASE_MAP(DSL_LINESTATE_SILENT, "Silent", LSTATE_MAP_SILENT)
STR_CASE_MAP(DSL_LINESTATE_HANDSHAKE, "Handshake", LSTATE_MAP_HANDSHAKE)
STR_CASE(DSL_LINESTATE_BONDING_CLR, "Bonding CLR")
STR_CASE_MAP(DSL_LINESTATE_FULL_INIT, "Full init", LSTATE_MAP_FULL_INIT)
STR_CASE(DSL_LINESTATE_SHORT_INIT_ENTRY, "Short init entry")
STR_CASE(DSL_LINESTATE_DISCOVERY, "Discovery")
STR_CASE(DSL_LINESTATE_TRAINING, "Training")
STR_CASE(DSL_LINESTATE_ANALYSIS, "Analysis")
STR_CASE(DSL_LINESTATE_EXCHANGE, "Exchange")
STR_CASE_MAP(DSL_LINESTATE_SHOWTIME_NO_SYNC, "Showtime without TC-Layer sync", LSTATE_MAP_SHOWTIME_NO_SYNC)
STR_CASE_MAP(DSL_LINESTATE_SHOWTIME_TC_SYNC, "Showtime with TC-Layer sync", LSTATE_MAP_SHOWTIME_TC_SYNC)
STR_CASE(DSL_LINESTATE_FASTRETRAIN, "Fastretrain")
STR_CASE(DSL_LINESTATE_LOWPOWER_L2, "Lowpower L2")
STR_CASE(DSL_LINESTATE_LOOPDIAGNOSTIC_ACTIVE, "Loopdiagnostic active")
STR_CASE(DSL_LINESTATE_LOOPDIAGNOSTIC_DATA_EXCHANGE, "Loopdiagnostic data exchange")
STR_CASE(DSL_LINESTATE_LOOPDIAGNOSTIC_DATA_REQUEST, "Loopdiagnostic data request")
STR_CASE(DSL_LINESTATE_LOOPDIAGNOSTIC_COMPLETE, "Loopdiagnostic complete")
STR_CASE_MAP(DSL_LINESTATE_RESYNC, "Resync", LSTATE_MAP_RESYNC)
STR_CASE(DSL_LINESTATE_TEST, "Test")
STR_CASE(DSL_LINESTATE_TEST_LOOP, "Test loop")
STR_CASE(DSL_LINESTATE_TEST_REVERB, "Test reverb")
STR_CASE(DSL_LINESTATE_TEST_MEDLEY, "Test medley")
STR_CASE(DSL_LINESTATE_TEST_SHOWTIME_LOCK, "Showtime lock")
STR_CASE(DSL_LINESTATE_TEST_QUIET, "Quiet")
STR_CASE(DSL_LINESTATE_LOWPOWER_L3, "Lowpower L3")
#ifndef INCLUDE_DSL_CPE_API_DANUBE
STR_CASE(DSL_LINESTATE_DISABLED, "Disabled")
STR_CASE(DSL_LINESTATE_T1413, "T1413")
STR_CASE(DSL_LINESTATE_ORDERLY_SHUTDOWN_REQUEST, "Orderly shutdown request")
STR_CASE(DSL_LINESTATE_ORDERLY_SHUTDOWN, "Orderly shutdown")
STR_CASE(DSL_LINESTATE_TEST_FILTERDETECTION_ACTIVE, "Test filterdetection active")
STR_CASE(DSL_LINESTATE_TEST_FILTERDETECTION_COMPLETE, "Test filterdetection complete")
#endif
default:
str = NULL;
break;
};
if (str)
m_str("state", str);
if (map != LSTATE_MAP_UNKNOWN )
m_u32("state_num", map);
m_bool("up", out.data.nLineState == DSL_LINESTATE_SHOWTIME_TC_SYNC);
}
static void pm_channel_counters_showtime(int fd) {
IOCTL_DIR(DSL_PM_ChannelCounters_t, DSL_FIO_PM_CHANNEL_COUNTERS_SHOWTIME_GET, DSL_NEAR_END);
m_u32("uptime", out.interval.nElapsedTime);
}
static void g997_line_inventory(int fd) {
IOCTL_DIR(DSL_G997_LineInventory_t, DSL_FIO_G997_LINE_INVENTORY_GET, DSL_DOWNSTREAM)
m_array("vendor_id", out.data.G994VendorID, DSL_G997_LI_MAXLEN_VENDOR_ID);
m_vendor("vendor", out.data.G994VendorID);
m_array("system_vendor_id", out.data.SystemVendorID, DSL_G997_LI_MAXLEN_VENDOR_ID);
m_vendor("system_vendor", out.data.SystemVendorID);
m_array("version", out.data.VersionNumber, DSL_G997_LI_MAXLEN_VERSION);
m_array("serial", out.data.SerialNumber, DSL_G997_LI_MAXLEN_SERIAL);
}
static void g997_power_management_status(int fd) {
IOCTL(DSL_G997_PowerManagementStatus_t, DSL_FIO_G997_POWER_MANAGEMENT_STATUS_GET)
int map = PSTATE_MAP_UNKNOWN;
const char *str;
switch (out.data.nPowerManagementStatus) {
STR_CASE_MAP(DSL_G997_PMS_NA, "Power management state is not available", PSTATE_MAP_NA)
STR_CASE_MAP(DSL_G997_PMS_L0, "L0 - Synchronized", PSTATE_MAP_L0)
STR_CASE_MAP(DSL_G997_PMS_L1, "L1 - Power Down Data transmission (G.992.2)", PSTATE_MAP_L1)
STR_CASE_MAP(DSL_G997_PMS_L2, "L2 - Power Down Data transmission (G.992.3 and G.992.4)", PSTATE_MAP_L2)
STR_CASE_MAP(DSL_G997_PMS_L3, "L3 - No power", PSTATE_MAP_L3)
default:
str = NULL;
break;
};
if (str)
m_str("power_state", str);
if (map != PSTATE_MAP_UNKNOWN)
m_u32("power_state_num", map);
}
static void g997_xtu_system_enabling(int fd, standard_t *standard) {
IOCTL(DSL_G997_XTUSystemEnabling_t, DSL_FIO_G997_XTU_SYSTEM_ENABLING_STATUS_GET)
m_array("xtse", out.data.XTSE, DSL_G997_NUM_XTSE_OCTETS);
const char *str;
switch (get_annex(out.data.XTSE)) {
STR_CASE(ANNEX_A, "A")
STR_CASE(ANNEX_B, "B")
STR_CASE(ANNEX_C, "C")
STR_CASE(ANNEX_I, "I")
STR_CASE(ANNEX_J, "J")
STR_CASE(ANNEX_L, "L")
STR_CASE(ANNEX_M, "M")
default:
str = NULL;
break;
};
if (str)
m_str("annex", str);
*standard = get_standard(out.data.XTSE);
switch (*standard) {
STR_CASE(STD_T1_413, "T1.413")
STR_CASE(STD_TS_101_388, "TS 101 388")
STR_CASE(STD_G_992_1, "G.992.1")
STR_CASE(STD_G_992_2, "G.992.2")
STR_CASE(STD_G_992_3, "G.992.3")
STR_CASE(STD_G_992_4, "G.992.4")
STR_CASE(STD_G_992_5, "G.992.5")
STR_CASE(STD_G_993_1, "G.993.1")
STR_CASE(STD_G_993_2, "G.993.2")
default:
str = NULL;
break;
}
if (str)
m_str("standard", str);
}
static vector_t get_vector_status() {
#ifdef INCLUDE_DSL_CPE_API_VRX
int fd = open(DSL_CPE_DSL_LOW_DEV "/0", O_RDWR, 0644);
if (fd < 0)
return VECTOR_UNKNOWN;
IOCTL_MEI_dsmStatus_t out;
memset(&out, 0, sizeof(IOCTL_MEI_dsmStatus_t));
int ret = ioctl(fd, FIO_MEI_DSM_STATUS_GET, &out);
close(fd);
if (ret)
return VECTOR_UNKNOWN;
switch (out.eVectorStatus) {
case e_MEI_VECTOR_STAT_OFF:
return VECTOR_OFF;
case e_MEI_VECTOR_STAT_ON_DS:
return VECTOR_ON_DS;
case e_MEI_VECTOR_STAT_ON_DS_US:
return VECTOR_ON_DS_US;
default:
return VECTOR_UNKNOWN;
};
#else
return VECTOR_UNKNOWN;
#endif
}
static void band_plan_status(int fd, profile_t *profile) {
#if (INCLUDE_DSL_CPE_API_VDSL_SUPPORT == 1)
IOCTL(DSL_BandPlanStatus_t, DSL_FIO_BAND_PLAN_STATUS_GET)
switch (out.data.nProfile) {
case DSL_PROFILE_8A:
*profile = PROFILE_8A;
break;
case DSL_PROFILE_8B:
*profile = PROFILE_8B;
break;
case DSL_PROFILE_8C:
*profile = PROFILE_8C;
break;
case DSL_PROFILE_8D:
*profile = PROFILE_8D;
break;
case DSL_PROFILE_12A:
*profile = PROFILE_12A;
break;
case DSL_PROFILE_12B:
*profile = PROFILE_12B;
break;
case DSL_PROFILE_17A:
*profile = PROFILE_17A;
break;
case DSL_PROFILE_30A:
*profile = PROFILE_30A;
break;
case DSL_PROFILE_35B:
*profile = PROFILE_35B;
break;
default:
*profile = PROFILE_UNKNOWN;
break;
};
const char *str;
switch (*profile) {
STR_CASE(PROFILE_8A, "8a")
STR_CASE(PROFILE_8B, "8b")
STR_CASE(PROFILE_8C, "8c")
STR_CASE(PROFILE_8D, "8d")
STR_CASE(PROFILE_12A, "12a")
STR_CASE(PROFILE_12B, "12b")
STR_CASE(PROFILE_17A, "17a")
STR_CASE(PROFILE_30A, "30a")
STR_CASE(PROFILE_35B, "35b")
default:
str = NULL;
break;
};
if (str)
m_str("profile", str);
#endif
}
static void line_feature_config(int fd, DSL_AccessDir_t direction) {
IOCTL_DIR(DSL_LineFeature_t, DSL_FIO_LINE_FEATURE_STATUS_GET, direction)
m_bool("trellis", out.data.bTrellisEnable);
m_bool("bitswap", out.data.bBitswapEnable);
m_bool("retx", out.data.bReTxEnable);
m_bool("virtual_noise", out.data.bVirtualNoiseSupport);
}
static void g997_channel_status(int fd, DSL_AccessDir_t direction) {
IOCTL_DIR(DSL_G997_ChannelStatus_t, DSL_FIO_G997_CHANNEL_STATUS_GET, direction);
m_u32("interleave_delay", out.data.ActualInterleaveDelay * 10);
#ifndef INCLUDE_DSL_CPE_API_DANUBE
// prefer ACTNDR, see comments in drv_dsl_cpe_api_g997.h
m_u32("data_rate", out.data.ActualNetDataRate);
#else
m_u32("data_rate", out.data.ActualDataRate);
#endif
}
static void g997_line_status(int fd, DSL_AccessDir_t direction) {
IOCTL_DIR_DELT(DSL_G997_LineStatus_t, DSL_FIO_G997_LINE_STATUS_GET, direction, DSL_DELT_DATA_SHOWTIME);
m_db("latn", out.data.LATN);
m_db("satn", out.data.SATN);
m_db("snr", out.data.SNR);
m_db("actps", out.data.ACTPS);
m_db("actatp", out.data.ACTATP);
m_u32("attndr", out.data.ATTNDR);
}
static void pm_line_sec_counters_total(int fd, DSL_XTUDir_t direction) {
IOCTL_DIR(DSL_PM_LineSecCountersTotal_t, DSL_FIO_PM_LINE_SEC_COUNTERS_TOTAL_GET, direction)
m_u32("es", out.data.nES);
m_u32("ses", out.data.nSES);
m_u32("loss", out.data.nLOSS);
m_u32("uas", out.data.nUAS);
m_u32("lofs", out.data.nLOFS);
#ifndef INCLUDE_DSL_CPE_API_DANUBE
m_u32("fecs", out.data.nFECS);
#endif
}
static void pm_data_path_counters_total(int fd, DSL_XTUDir_t direction) {
IOCTL_DIR(DSL_PM_DataPathCountersTotal_t, DSL_FIO_PM_DATA_PATH_COUNTERS_TOTAL_GET, direction);
m_u32("hec", out.data.nHEC);
m_u32("ibe", out.data.nIBE);
m_u32("crc_p", out.data.nCRC_P);
m_u32("crcp_p", out.data.nCRCP_P);
m_u32("cv_p", out.data.nCV_P);
m_u32("cvp_p", out.data.nCVP_P);
}
static void retx_statistics(int fd, DSL_XTUDir_t direction) {
#ifdef INCLUDE_DSL_CPE_PM_RETX_COUNTERS
#ifdef INCLUDE_DSL_CPE_PM_RETX_THRESHOLDS
IOCTL_DIR(DSL_ReTxStatistics_t, DSL_FIO_RETX_STATISTICS_GET, direction);
m_u32("rx_corrupted", out.data.nRxCorruptedTotal);
m_u32("rx_uncorrected_protected", out.data.nRxUncorrectedProtected);
m_u32("rx_retransmitted", out.data.nRxRetransmitted);
m_u32("rx_corrected", out.data.nRxCorrected);
m_u32("tx_retransmitted", out.data.nTxRetransmitted);
#endif
#endif
}
static void describe_mode(standard_t standard, profile_t profile, vector_t vector) {
char buf[128];
switch (standard) {
case STD_T1_413:
strcpy(buf, "T1.413");
break;
case STD_TS_101_388:
strcpy(buf, "TS 101 388");
break;
case STD_G_992_1:
strcpy(buf, "G.992.1 (ADSL)");
break;
case STD_G_992_2:
strcpy(buf, "G.992.2 (ADSL lite)");
break;
case STD_G_992_3:
strcpy(buf, "G.992.3 (ADSL2)");
break;
case STD_G_992_4:
strcpy(buf, "G.992.4 (ADSL2 lite)");
break;
case STD_G_992_5:
strcpy(buf, "G.992.5 (ADSL2+)");
break;
case STD_G_993_1:
strcpy(buf, "G.993.1 (VDSL)");
break;
case STD_G_993_2:
strcpy(buf, "G.993.2 (VDSL2");
switch (profile) {
case PROFILE_8A:
strcat(buf, ", Profile 8a");
break;
case PROFILE_8B:
strcat(buf, ", Profile 8b");
break;
case PROFILE_8C:
strcat(buf, ", Profile 8c");
break;
case PROFILE_8D:
strcat(buf, ", Profile 8d");
break;
case PROFILE_12A:
strcat(buf, ", Profile 12a");
break;
case PROFILE_12B:
strcat(buf, ", Profile 12b");
break;
case PROFILE_17A:
strcat(buf, ", Profile 17a");
break;
case PROFILE_30A:
strcat(buf, ", Profile 30a");
break;
case PROFILE_35B:
strcat(buf, ", Profile 35b");
break;
default:
break;
};
switch (vector) {
case VECTOR_ON_DS:
strcat(buf, ", with downstream vectoring");
break;
case VECTOR_ON_DS_US:
strcat(buf, ", with down- and upstream vectoring");
break;
default:
break;
};
strcat(buf, ")");
break;
default:
return;
};
m_str("mode", buf);
}
static int metrics(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
int fd;
void *c, *c2;
standard_t standard = STD_UNKNOWN;
profile_t profile = PROFILE_UNKNOWN;
vector_t vector = VECTOR_UNKNOWN;
#ifndef INCLUDE_DSL_CPE_API_DANUBE
fd = open(DSL_CPE_DEVICE_NAME "0", O_RDWR, 0644);
#else
fd = open(DSL_CPE_DEVICE_NAME, O_RDWR, 0644);
#endif
if (fd < 0)
return UBUS_STATUS_UNKNOWN_ERROR;
blob_buf_init(&b, 0);
version_information(fd);
line_state(fd);
pm_channel_counters_showtime(fd);
c = blobmsg_open_table(&b, "atu_c");
g997_line_inventory(fd);
blobmsg_close_table(&b, c);
g997_power_management_status(fd);
g997_xtu_system_enabling(fd, &standard);
if (standard == STD_G_993_2) {
band_plan_status(fd, &profile);
vector = get_vector_status();
}
describe_mode(standard, profile, vector);
c = blobmsg_open_table(&b, "upstream");
switch (vector) {
case VECTOR_OFF:
m_bool("vector", false);
break;
case VECTOR_ON_DS_US:
m_bool("vector", true);
break;
default:
break;
};
line_feature_config(fd, DSL_UPSTREAM);
g997_channel_status(fd, DSL_UPSTREAM);
g997_line_status(fd, DSL_UPSTREAM);
blobmsg_close_table(&b, c);
c = blobmsg_open_table(&b, "downstream");
switch (vector) {
case VECTOR_OFF:
m_bool("vector", false);
break;
case VECTOR_ON_DS:
case VECTOR_ON_DS_US:
m_bool("vector", true);
break;
default:
break;
};
line_feature_config(fd, DSL_DOWNSTREAM);
g997_channel_status(fd, DSL_DOWNSTREAM);
g997_line_status(fd, DSL_DOWNSTREAM);
blobmsg_close_table(&b, c);
c = blobmsg_open_table(&b, "errors");
c2 = blobmsg_open_table(&b, "near");
pm_line_sec_counters_total(fd, DSL_NEAR_END);
pm_data_path_counters_total(fd, DSL_NEAR_END);
retx_statistics(fd, DSL_NEAR_END);
blobmsg_close_table(&b, c2);
c2 = blobmsg_open_table(&b, "far");
pm_line_sec_counters_total(fd, DSL_FAR_END);
pm_data_path_counters_total(fd, DSL_FAR_END);
retx_statistics(fd, DSL_FAR_END);
blobmsg_close_table(&b, c2);
blobmsg_close_table(&b, c);
ubus_send_reply(ctx, req, b.head);
close(fd);
return 0;
}
static const struct ubus_method dsl_methods[] = {
UBUS_METHOD_NOARG("metrics", metrics),
};
static struct ubus_object_type dsl_object_type =
UBUS_OBJECT_TYPE("dsl", dsl_methods);
static struct ubus_object dsl_object = {
.name = "dsl",
.type = &dsl_object_type,
.methods = dsl_methods,
.n_methods = ARRAY_SIZE(dsl_methods),
};
static DSL_int_t ubus_main(DSL_CPE_Thread_Params_t *params) {
uloop_run();
return 0;
}
void ubus_init() {
uloop_init();
ctx = ubus_connect(NULL);
if (!ctx)
return;
if (ubus_add_object(ctx, &dsl_object)) {
ubus_free(ctx);
ctx = NULL;
return;
}
ubus_add_uloop(ctx);
DSL_CPE_ThreadInit(&thread, "ubus", ubus_main, DSL_CPE_PIPE_STACK_SIZE, DSL_CPE_PIPE_PRIORITY, 0, 0);
}
void ubus_deinit() {
if (!ctx)
return;
ubus_free(ctx);
uloop_done();
DSL_CPE_ThreadShutdown(&thread, 1000);
}

View File

@@ -0,0 +1,50 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=netifd
PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git
PKG_SOURCE_DATE:=2021-10-13
PKG_SOURCE_VERSION:=7a048bd6871df952ff1324bec7175891c9b38f99
PKG_MIRROR_HASH:=b4fdca3c45713710f4ea69f1ed0fb16d3b07b70002e6b39640ce6e56364817d0
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_LICENSE:=GPL-2.0
PKG_LICENSE_FILES:=
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/netifd
SECTION:=base
CATEGORY:=Base system
DEPENDS:=+libuci +libnl-tiny +libubus +ubus +ubusd +jshn +libubox
TITLE:=OpenWrt Network Interface Configuration Daemon
endef
define Package/netifd/conffiles
/etc/udhcpc.user
/etc/udhcpc.user.d/
endef
TARGET_CFLAGS += \
-I$(STAGING_DIR)/usr/include/libnl-tiny \
-I$(STAGING_DIR)/usr/include \
-flto
TARGET_LDFLAGS += -flto -fuse-linker-plugin
CMAKE_OPTIONS += \
-DLIBNL_LIBS=-lnl-tiny \
-DDEBUG=1
define Package/netifd/install
$(INSTALL_DIR) $(1)/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/netifd $(1)/sbin/
$(CP) ./files/* $(1)/
$(INSTALL_DIR) $(1)/etc/udhcpc.user.d/
$(CP) $(PKG_BUILD_DIR)/scripts/* $(1)/lib/netifd/
endef
$(eval $(call BuildPackage,netifd))

View File

@@ -0,0 +1,6 @@
[ ifup = "$ACTION" ] && {
uci_toggle_state network "$INTERFACE" up 1
[ -n "$DEVICE" ] && {
uci_toggle_state network "$INTERFACE" ifname "$DEVICE"
}
}

View File

@@ -0,0 +1,67 @@
#!/bin/sh
[ "$ACTION" = add ] || exit
NPROCS="$(grep -c "^processor.*:" /proc/cpuinfo)"
[ "$NPROCS" -gt 1 ] || exit
PROC_MASK="$(( (1 << $NPROCS) - 1 ))"
find_irq_cpu() {
local dev="$1"
local match="$(grep -m 1 "$dev\$" /proc/interrupts)"
local cpu=0
[ -n "$match" ] && {
set -- $match
shift
for cur in $(seq 1 $NPROCS); do
[ "$1" -gt 0 ] && {
cpu=$(($cur - 1))
break
}
shift
done
}
echo "$cpu"
}
set_hex_val() {
local file="$1"
local val="$2"
val="$(printf %x "$val")"
[ -n "$DEBUG" ] && echo "$file = $val"
echo "$val" > "$file"
}
packet_steering="$(uci get "network.@globals[0].packet_steering")"
[ "$packet_steering" != 1 ] && exit 0
exec 512>/var/lock/smp_tune.lock
flock 512 || exit 1
for dev in /sys/class/net/*; do
[ -d "$dev" ] || continue
# ignore virtual interfaces
[ -n "$(ls "${dev}/" | grep '^lower_')" ] && continue
[ -d "${dev}/device" ] || continue
device="$(readlink "${dev}/device")"
device="$(basename "$device")"
irq_cpu="$(find_irq_cpu "$device")"
irq_cpu_mask="$((1 << $irq_cpu))"
for q in ${dev}/queues/tx-*; do
set_hex_val "$q/xps_cpus" "$PROC_MASK"
done
# ignore dsa slave ports for RPS
subsys="$(readlink "${dev}/device/subsystem")"
subsys="$(basename "$subsys")"
[ "$subsys" = "mdio_bus" ] && continue
for q in ${dev}/queues/rx-*; do
set_hex_val "$q/rps_cpus" "$PROC_MASK"
done
done

View File

@@ -0,0 +1,144 @@
#!/bin/sh /etc/rc.common
START=20
STOP=90
USE_PROCD=1
init_switch() {
setup_switch() { return 0; }
include /lib/network
setup_switch
}
start_service() {
init_switch
procd_open_instance
procd_set_param command /sbin/netifd
procd_set_param respawn
procd_set_param watch network.interface
[ -e /proc/sys/kernel/core_pattern ] && {
procd_set_param limits core="unlimited"
}
procd_close_instance
}
reload_service() {
local rv=0
init_switch
ubus call network reload || rv=1
/sbin/wifi reload_legacy
return $rv
}
stop_service() {
/sbin/wifi down
ifdown -a
sleep 1
}
validate_atm_bridge_section()
{
uci_validate_section network "atm-bridge" "${1}" \
'unit:uinteger:0' \
'vci:range(32, 65535):35' \
'vpi:range(0, 255):8' \
'atmdev:uinteger:0' \
'encaps:or("llc", "vc"):llc' \
'payload:or("bridged", "routed"):bridged'
}
validate_route_section()
{
uci_validate_section network route "${1}" \
'interface:string' \
'target:cidr4' \
'netmask:netmask4' \
'gateway:ip4addr' \
'metric:uinteger' \
'mtu:uinteger' \
'table:or(range(0,65535),string)'
}
validate_route6_section()
{
uci_validate_section network route6 "${1}" \
'interface:string' \
'target:cidr6' \
'gateway:ip6addr' \
'metric:uinteger' \
'mtu:uinteger' \
'table:or(range(0,65535),string)'
}
validate_rule_section()
{
uci_validate_section network rule "${1}" \
'in:string' \
'out:string' \
'src:cidr4' \
'dest:cidr4' \
'tos:range(0,31)' \
'mark:string' \
'invert:bool' \
'lookup:or(range(0,65535),string)' \
'goto:range(0,65535)' \
'action:or("prohibit", "unreachable", "blackhole", "throw")'
}
validate_rule6_section()
{
uci_validate_section network rule6 "${1}" \
'in:string' \
'out:string' \
'src:cidr6' \
'dest:cidr6' \
'tos:range(0,31)' \
'mark:string' \
'invert:bool' \
'lookup:or(range(0,65535),string)' \
'goto:range(0,65535)' \
'action:or("prohibit", "unreachable", "blackhole", "throw")'
}
validate_switch_section()
{
uci_validate_section network switch "${1}" \
'name:string' \
'enable:bool' \
'enable_vlan:bool' \
'reset:bool' \
'ar8xxx_mib_poll_interval:uinteger' \
'ar8xxx_mib_type:range(0,1)'
}
validate_switch_vlan()
{
uci_validate_section network switch_vlan "${1}" \
'device:string' \
'vlan:uinteger' \
'ports:list(ports)'
}
service_triggers()
{
procd_add_reload_trigger network wireless
procd_open_validate
validate_atm_bridge_section
validate_route_section
[ -e /proc/sys/net/ipv6 ] && validate_route6_section
validate_rule_section
[ -e /proc/sys/net/ipv6 ] && validate_rule6_section
validate_switch_section
validate_switch_vlan
procd_close_validate
}
shutdown() {
ifdown -a
sleep 1
}

View File

@@ -0,0 +1,23 @@
. /lib/functions.sh
migrate_release() {
local config="$1"
local proto
local release
config_get proto "$config" proto
config_get release "$config" release
[ "$proto" = "dhcp" ] && [ -n "$release" ] && {
norelease="$((!$release))"
uci_set network "$config" norelease "$norelease"
uci_remove network "$config" release
}
}
config_load network
config_foreach migrate_release interface
uci commit network
exit 0

View File

@@ -0,0 +1 @@
# This script is sourced by udhcpc's dhcp.script at every DHCP event.

View File

@@ -0,0 +1,119 @@
#!/bin/sh
[ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1
. /lib/functions.sh
. /lib/netifd/netifd-proto.sh
set_classless_routes() {
local max=128
while [ -n "$1" -a -n "$2" -a $max -gt 0 ]; do
proto_add_ipv4_route "${1%%/*}" "${1##*/}" "$2" "$ip"
max=$(($max-1))
shift 2
done
}
setup_interface () {
proto_init_update "*" 1
proto_add_ipv4_address "$ip" "${subnet:-255.255.255.0}"
# TODO: apply $broadcast
local ip_net
eval "$(ipcalc.sh "$ip/$mask")";ip_net="$NETWORK"
local i
for i in $router; do
local gw_net
eval "$(ipcalc.sh "$i/$mask")";gw_net="$NETWORK"
[ "$ip_net" != "$gw_net" ] && proto_add_ipv4_route "$i" 32 "" "$ip"
proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip"
local r
for r in $CUSTOMROUTES; do
proto_add_ipv4_route "${r%%/*}" "${r##*/}" "$i" "$ip"
done
done
# CIDR STATIC ROUTES (rfc3442)
[ -n "$staticroutes" ] && set_classless_routes $staticroutes
[ -n "$msstaticroutes" ] && set_classless_routes $msstaticroutes
for i in $dns; do
proto_add_dns_server "$i"
done
for i in $domain; do
proto_add_dns_search "$i"
done
# TODO: Deprecate timesvr in favor of timesrv
if [ -n "$timesvr" -a -z "$timesrv" ]; then
timesrv="$timesvr"
echo "Environment variable 'timesvr' will be deprecated; use 'timesrv' instead."
fi
proto_add_data
[ -n "$ZONE" ] && json_add_string zone "$ZONE"
[ -n "$ntpsrv" ] && json_add_string ntpserver "$ntpsrv"
[ -n "$timesrv" ] && json_add_string timeserver "$timesrv"
[ -n "$hostname" ] && json_add_string hostname "$hostname"
[ -n "$message" ] && json_add_string message "$message"
[ -n "$timezone" ] && json_add_int timezone "$timezone"
[ -n "$lease" ] && json_add_int leasetime "$lease"
proto_close_data
proto_send_update "$INTERFACE"
if [ "$IFACE6RD" != 0 -a -n "$ip6rd" ]; then
local v4mask="${ip6rd%% *}"
ip6rd="${ip6rd#* }"
local ip6rdprefixlen="${ip6rd%% *}"
ip6rd="${ip6rd#* }"
local ip6rdprefix="${ip6rd%% *}"
ip6rd="${ip6rd#* }"
local ip6rdbr="${ip6rd%% *}"
[ -n "$ZONE" ] || ZONE=$(fw3 -q network $INTERFACE 2>/dev/null)
[ -z "$IFACE6RD" -o "$IFACE6RD" = 1 ] && IFACE6RD=${INTERFACE}_6
json_init
json_add_string name "$IFACE6RD"
json_add_string ifname "@$INTERFACE"
json_add_string proto "6rd"
json_add_string peeraddr "$ip6rdbr"
json_add_int ip4prefixlen "$v4mask"
json_add_string ip6prefix "$ip6rdprefix"
json_add_int ip6prefixlen "$ip6rdprefixlen"
json_add_string tunlink "$INTERFACE"
[ -n "$IFACE6RD_DELEGATE" ] && json_add_boolean delegate "$IFACE6RD_DELEGATE"
[ -n "$ZONE6RD" ] || ZONE6RD=$ZONE
[ -n "$ZONE6RD" ] && json_add_string zone "$ZONE6RD"
[ -n "$MTU6RD" ] && json_add_string mtu "$MTU6RD"
json_close_object
ubus call network add_dynamic "$(json_dump)"
fi
}
deconfig_interface() {
proto_init_update "*" 0
proto_send_update "$INTERFACE"
}
case "$1" in
deconfig)
deconfig_interface
;;
renew|bound)
setup_interface
;;
esac
# user rules
[ -f /etc/udhcpc.user ] && . /etc/udhcpc.user "$@"
for f in /etc/udhcpc.user.d/*; do
[ -f "$f" ] && (. "$f" "$@")
done
exit 0

View File

@@ -0,0 +1,88 @@
#!/bin/sh
[ -L /sbin/udhcpc ] || exit 0
. /lib/functions.sh
. ../netifd-proto.sh
init_proto "$@"
proto_dhcp_init_config() {
renew_handler=1
proto_config_add_string 'ipaddr:ipaddr'
proto_config_add_string 'hostname:hostname'
proto_config_add_string clientid
proto_config_add_string vendorid
proto_config_add_boolean 'broadcast:bool'
proto_config_add_boolean 'norelease:bool'
proto_config_add_string 'reqopts:list(string)'
proto_config_add_boolean 'defaultreqopts:bool'
proto_config_add_string iface6rd
proto_config_add_array 'sendopts:list(string)'
proto_config_add_boolean delegate
proto_config_add_string zone6rd
proto_config_add_string zone
proto_config_add_string mtu6rd
proto_config_add_string customroutes
proto_config_add_boolean classlessroute
}
proto_dhcp_add_sendopts() {
[ -n "$1" ] && append "$3" "-x $1"
}
proto_dhcp_setup() {
local config="$1"
local iface="$2"
local ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd sendopts delegate zone6rd zone mtu6rd customroutes classlessroute
json_get_vars ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd delegate zone6rd zone mtu6rd customroutes classlessroute
local opt dhcpopts
for opt in $reqopts; do
append dhcpopts "-O $opt"
done
json_for_each_item proto_dhcp_add_sendopts sendopts dhcpopts
[ -z "$hostname" ] && hostname="$(cat /proc/sys/kernel/hostname)"
[ "$hostname" = "*" ] && hostname=
[ "$defaultreqopts" = 0 ] && defaultreqopts="-o" || defaultreqopts=
[ "$broadcast" = 1 ] && broadcast="-B" || broadcast=
[ "$norelease" = 1 ] && norelease="" || norelease="-R"
[ -n "$clientid" ] && clientid="-x 0x3d:${clientid//:/}" || clientid="-C"
[ -n "$iface6rd" ] && proto_export "IFACE6RD=$iface6rd"
[ "$iface6rd" != 0 -a -f /lib/netifd/proto/6rd.sh ] && append dhcpopts "-O 212"
[ -n "$zone6rd" ] && proto_export "ZONE6RD=$zone6rd"
[ -n "$zone" ] && proto_export "ZONE=$zone"
[ -n "$mtu6rd" ] && proto_export "MTU6RD=$mtu6rd"
[ -n "$customroutes" ] && proto_export "CUSTOMROUTES=$customroutes"
[ "$delegate" = "0" ] && proto_export "IFACE6RD_DELEGATE=0"
# Request classless route option (see RFC 3442) by default
[ "$classlessroute" = "0" ] || append dhcpopts "-O 121"
proto_export "INTERFACE=$config"
proto_run_command "$config" udhcpc \
-p /var/run/udhcpc-$iface.pid \
-s /lib/netifd/dhcp.script \
-f -t 0 -i "$iface" \
${ipaddr:+-r $ipaddr} \
${hostname:+-x "hostname:$hostname"} \
${vendorid:+-V "$vendorid"} \
$clientid $defaultreqopts $broadcast $norelease $dhcpopts
}
proto_dhcp_renew() {
local interface="$1"
# SIGUSR1 forces udhcpc to renew its lease
local sigusr1="$(kill -l SIGUSR1)"
[ -n "$sigusr1" ] && proto_kill_command "$interface" $sigusr1
}
proto_dhcp_teardown() {
local interface="$1"
proto_kill_command "$interface"
}
add_protocol dhcp

View File

@@ -0,0 +1,76 @@
#!/bin/sh
# Copyright (C) 2011 OpenWrt.org
. /usr/share/libubox/jshn.sh
find_config() {
local device="$1"
local ifdev ifl3dev ifobj
for ifobj in $(ubus list network.interface.\*); do
interface="${ifobj##network.interface.}"
(
json_load "$(ifstatus $interface)"
json_get_var ifdev device
json_get_var ifl3dev l3_device
if [ "$device" = "$ifdev" ] || [ "$device" = "$ifl3dev" ]; then
echo "$interface"
exit 0
else
exit 1
fi
) && return
done
}
unbridge() {
return
}
ubus_call() {
json_init
local _data="$(ubus -S call "$1" "$2")"
[ -z "$_data" ] && return 1
json_load "$_data"
return 0
}
fixup_interface() {
local config="$1"
local ifname type device l3dev
config_get type "$config" type
config_get ifname "$config" ifname
[ "bridge" = "$type" ] && ifname="br-$config"
ubus_call "network.interface.$config" status || return 0
json_get_var l3dev l3_device
[ -n "$l3dev" ] && ifname="$l3dev"
json_init
config_set "$config" ifname "$ifname"
}
scan_interfaces() {
config_load network
config_foreach fixup_interface interface
}
prepare_interface_bridge() {
local config="$1"
[ -n "$config" ] || return 0
ubus call network.interface."$config" prepare
}
setup_interface() {
local iface="$1"
local config="$2"
[ -n "$config" ] || return 0
ubus call network.interface."$config" add_device "{ \"name\": \"$iface\" }"
}
do_sysctl() {
[ -n "$2" ] && \
sysctl -n -e -w "$1=$2" >/dev/null || \
sysctl -n -e "$1"
}

View File

@@ -0,0 +1,12 @@
#!/bin/sh
. /usr/share/libubox/jshn.sh
DEVICE="$1"
[ -n "$DEVICE" ] || {
echo "Usage: $0 <device>"
exit 1
}
json_init
json_add_string name "$DEVICE"
ubus call network.device status "$(json_dump)"

View File

@@ -0,0 +1 @@
ifup

View File

@@ -0,0 +1,13 @@
#!/bin/sh
INTERFACE="$1"
[ -n "$INTERFACE" ] || {
echo "Usage: $0 <interface>"
exit 1
}
ubus -S list "network.interface.$INTERFACE" >/dev/null || {
echo "Interface $INTERFACE not found"
exit 1
}
ubus call network.interface status "{ \"interface\" : \"$INTERFACE\" }"

View File

@@ -0,0 +1,77 @@
#!/bin/sh
ifup_all=
setup_wifi=
if_call() {
local interface="$1"
for mode in $modes; do
ubus call network.interface $mode "{ \"interface\" : \"$interface\" }"
done
}
case "$0" in
*ifdown) modes=down;;
*ifup)
modes="down up"
setup_wifi=1
;;
*) echo "Invalid command: $0";;
esac
while :; do
case "$1" in
-a)
ifup_all=1
shift
;;
-w)
setup_wifi=
shift
;;
*)
break
;;
esac
done
[ "$modes" = "down up" ] && ubus call network reload
if [ -n "$ifup_all" ]; then
for interface in $(ubus -S list 'network.interface.*'); do
if_call "${interface##network.interface.}"
done
[ -n "$setup_wifi" ] && /sbin/wifi up
exit
else
ubus -S list "network.interface.$1" > /dev/null || {
echo "Interface $1 not found"
exit
}
if_call "$1"
fi
if [ -n "$setup_wifi" ] && grep -sq config /etc/config/wireless; then
. /lib/functions.sh
find_related_radios() {
local wdev wnet
config_get wdev "$1" device
config_get wnet "$1" network
if [ -n "$wdev" ]; then
for wnet in $wnet; do
if [ "$wnet" = "$network" ]; then
append radio_devs "$wdev" "$N"
fi
done
fi
}
network="$1"
config_load wireless
config_foreach find_related_radios wifi-iface
for dev in $(echo "$radio_devs" | sort -u); do
/sbin/wifi up "$dev"
done
fi

View File

@@ -0,0 +1,57 @@
#!/bin/sh
[ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1
set_classless_routes() {
local max=128
local type
while [ -n "$1" -a -n "$2" -a $max -gt 0 ]; do
[ ${1##*/} -eq 32 ] && type=host || type=net
echo "udhcpc: adding route for $type $1 via $2"
route add -$type "$1" gw "$2" dev "$interface"
max=$(($max-1))
shift 2
done
}
setup_interface() {
echo "udhcpc: ip addr add $ip/${subnet:-255.255.255.0} broadcast ${broadcast:-+} dev $interface"
ip addr add $ip/${subnet:-255.255.255.0} broadcast ${broadcast:-+} dev $interface
[ -n "$router" ] && [ "$router" != "0.0.0.0" ] && [ "$router" != "255.255.255.255" ] && {
echo "udhcpc: setting default routers: $router"
local valid_gw=""
for i in $router ; do
route add default gw $i dev $interface
valid_gw="${valid_gw:+$valid_gw|}$i"
done
eval $(route -n | awk '
/^0.0.0.0\W{9}('$valid_gw')\W/ {next}
/^0.0.0.0/ {print "route del -net "$1" gw "$2";"}
')
}
# CIDR STATIC ROUTES (rfc3442)
[ -n "$staticroutes" ] && set_classless_routes $staticroutes
[ -n "$msstaticroutes" ] && set_classless_routes $msstaticroutes
}
applied=
case "$1" in
deconfig)
ip -4 addr flush dev "$interface"
;;
renew)
setup_interface update
;;
bound)
setup_interface ifup
;;
esac
# user rules
[ -f /etc/udhcpc.user ] && . /etc/udhcpc.user
exit 0

View File

@@ -0,0 +1,53 @@
#
# 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:=qos-scripts
PKG_VERSION:=1.3.1
PKG_RELEASE:=$(AUTORELEASE)
PKG_LICENSE:=GPL-2.0
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/qos-scripts
SECTION:=utils
CATEGORY:=Base system
DEPENDS:=+tc +kmod-sched-core +kmod-sched-connmark +kmod-ifb +iptables +iptables-mod-ipopt +iptables-mod-conntrack-extra
TITLE:=QoS scripts
PKGARCH:=all
endef
define Package/qos-scripts/description
A set of scripts that abstract QoS configuration into a simple
configuration file supporting stanzas that specify any number of QoS
entries.
endef
define Package/qos-scripts/conffiles
/etc/config/qos
endef
define Build/Prepare
endef
define Build/Configure
endef
define Build/Compile
endef
define Package/qos-scripts/install
$(INSTALL_DIR) $(1)
$(CP) ./files/* $(1)/
endef
$(eval $(call BuildPackage,qos-scripts))

View File

@@ -0,0 +1,68 @@
# QoS configuration for OpenWrt
# INTERFACES:
config interface wan
option classgroup "Default"
option enabled 0
option upload 128
option download 1024
# RULES:
config classify
option target "Priority"
option ports "22,53"
option comment "ssh, dns"
config classify
option target "Normal"
option proto "tcp"
option ports "20,21,25,80,110,443,993,995"
option comment "ftp, smtp, http(s), imap"
config classify
option target "Express"
option ports "5190"
option comment "AOL, iChat, ICQ"
config default
option target "Express"
option proto "udp"
option pktsize "-500"
config reclassify
option target "Priority"
option proto "icmp"
config default
option target "Bulk"
option portrange "1024-65535"
# Don't change the stuff below unless you
# really know what it means :)
config classgroup "Default"
option classes "Priority Express Normal Bulk"
option default "Normal"
config class "Priority"
option packetsize 400
option avgrate 10
option priority 20
config class "Priority_down"
option packetsize 1000
option avgrate 10
config class "Express"
option packetsize 1000
option avgrate 50
option priority 10
config class "Normal"
option packetsize 1500
option packetdelay 100
option avgrate 10
option priority 5
config class "Normal_down"
option avgrate 20
config class "Bulk"
option avgrate 1
option packetdelay 200

View File

@@ -0,0 +1,2 @@
#!/bin/sh
[ "$ACTION" = ifup ] && /etc/init.d/qos enabled && /usr/lib/qos/generate.sh interface "$INTERFACE" | sh

View File

@@ -0,0 +1,28 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2006 OpenWrt.org
START=50
USE_PROCD=1
validate_qos_section()
{
uci_validate_section qos interface "${1}" \
'enabled:bool' \
'upload:uinteger' \
'download:uinteger'
}
service_triggers()
{
procd_add_reload_trigger "qos"
procd_add_validation validate_qos_section
qos-start
}
start_service() {
qos-start
}
reload_service() {
qos-start
}

View File

@@ -0,0 +1,4 @@
#!/bin/sh
qos-stop
/usr/lib/qos/generate.sh all | sh

View File

@@ -0,0 +1,68 @@
#!/bin/sh
# Copyright (C) 2011 OpenWrt.org
. /lib/functions.sh
include /lib/network
get_ifname() {
local interface="$1"
local cfgt
scan_interfaces
config_get cfgt "$interface" TYPE
[ "$cfgt" = "interface" ] && config_get "$interface" ifname
}
qos_set_device() {
config_get TYPE "$1" TYPE
[ "interface" = "$TYPE" ] && {
config_get device "$1" ifname
[ -z "$device" ] && device="$(get_ifname $1)"
config_set "$1" device "$device"
}
}
config_load qos
config_foreach qos_set_device
print_comments() {
echo ''
echo '# Interface: '"$1"
echo '# Direction: '"$2"
echo '# Stats: '"$3"
echo ''
}
get_device() {
( config_load network; scan_interfaces; config_get "$1" ifname )
}
interface_stats() {
local interface="$1"
local device
device="$(get_device "$interface")"
[ -z "$device" ] && config_get device "$interface" device
config_get_bool enabled "$interface" enabled 1
[ -z "$device" -o 1 -ne "$enabled" ] && {
return 1
}
config_get_bool halfduplex "$interface" halfduplex 0
if [ 1 -ne "$halfduplex" ]; then
unset halfduplex
print_comments "$interface" "Egress" "Start"
tc -s class show dev "$device"
print_comments "$interface" "Egress" "End"
id="root"
else
id=""
fi
print_comments "$interface" "Ingress${halfduplex:+/Egress}" "Start"
tc -s class show dev "$(tc filter show dev $device $id | grep mirred | sed -e 's,.*\(ifb.*\)).*,\1,')"
print_comments "$interface" "Ingress${halfduplex:+/Egress}" "End"
}
[ -z "$1" ] && config_foreach interface_stats interface || interface_stats "$1"

View File

@@ -0,0 +1,7 @@
#!/bin/sh
for iface in $(tc qdisc show | grep -E '(hfsc|ingress)' | awk '{print $5}'); do
tc qdisc del dev "$iface" ingress 2>&- >&-
tc qdisc del dev "$iface" root 2>&- >&-
done
/usr/lib/qos/generate.sh firewall stop | sh

View File

@@ -0,0 +1,543 @@
#!/bin/sh
[ -e /lib/functions.sh ] && . /lib/functions.sh || . ./functions.sh
[ -x /sbin/modprobe ] && {
insmod="modprobe"
rmmod="$insmod -r"
} || {
insmod="insmod"
rmmod="rmmod"
}
add_insmod() {
eval "export isset=\${insmod_$1}"
case "$isset" in
1) ;;
*) {
[ "$2" ] && append INSMOD "$rmmod $1 >&- 2>&-" "$N"
append INSMOD "$insmod $* >&- 2>&-" "$N"; export insmod_$1=1
};;
esac
}
[ -e /etc/config/network ] && {
# only try to parse network config on openwrt
. /lib/functions/network.sh
find_ifname() {
local ifname
if network_get_device ifname "$1"; then
echo "$ifname"
else
echo "Device for interface $1 not found." >&2
exit 1
fi
}
} || {
find_ifname() {
echo "Interface not found." >&2
exit 1
}
}
parse_matching_rule() {
local var="$1"
local section="$2"
local options="$3"
local prefix="$4"
local suffix="$5"
local proto="$6"
local mport=""
local ports=""
append "$var" "$prefix" "$N"
for option in $options; do
case "$option" in
proto) config_get value "$section" proto; proto="${proto:-$value}";;
esac
done
config_get type "$section" TYPE
case "$type" in
classify) unset pkt; append "$var" "-m mark --mark 0/0x0f";;
default) pkt=1; append "$var" "-m mark --mark 0/0xf0";;
reclassify) pkt=1;;
esac
append "$var" "${proto:+-p $proto}"
for option in $options; do
config_get value "$section" "$option"
case "$pkt:$option" in
*:srchost)
append "$var" "-s $value"
;;
*:dsthost)
append "$var" "-d $value"
;;
*:ports|*:srcports|*:dstports)
value="$(echo "$value" | sed -e 's,-,:,g')"
lproto=${lproto:-tcp}
case "$proto" in
""|tcp|udp) append "$var" "-m ${proto:-tcp -p tcp} -m multiport";;
*) unset "$var"; return 0;;
esac
case "$option" in
ports)
config_set "$section" srcports ""
config_set "$section" dstports ""
config_set "$section" portrange ""
append "$var" "--ports $value"
;;
srcports)
config_set "$section" ports ""
config_set "$section" dstports ""
config_set "$section" portrange ""
append "$var" "--sports $value"
;;
dstports)
config_set "$section" ports ""
config_set "$section" srcports ""
config_set "$section" portrange ""
append "$var" "--dports $value"
;;
esac
ports=1
;;
*:portrange)
config_set "$section" ports ""
config_set "$section" srcports ""
config_set "$section" dstports ""
value="$(echo "$value" | sed -e 's,-,:,g')"
case "$proto" in
""|tcp|udp) append "$var" "-m ${proto:-tcp -p tcp} --sport $value --dport $value";;
*) unset "$var"; return 0;;
esac
ports=1
;;
*:connbytes)
value="$(echo "$value" | sed -e 's,-,:,g')"
add_insmod xt_connbytes
append "$var" "-m connbytes --connbytes $value --connbytes-dir both --connbytes-mode bytes"
;;
*:comment)
add_insmod xt_comment
append "$var" "-m comment --comment '$value'"
;;
*:tos)
add_insmod xt_dscp
case "$value" in
!*) append "$var" "-m tos ! --tos $value";;
*) append "$var" "-m tos --tos $value"
esac
;;
*:dscp)
add_insmod xt_dscp
dscp_option="--dscp"
[ -z "${value%%[EBCA]*}" ] && dscp_option="--dscp-class"
case "$value" in
!*) append "$var" "-m dscp ! $dscp_option $value";;
*) append "$var" "-m dscp $dscp_option $value"
esac
;;
*:direction)
value="$(echo "$value" | sed -e 's,-,:,g')"
if [ "$value" = "out" ]; then
append "$var" "-o $device"
elif [ "$value" = "in" ]; then
append "$var" "-i $device"
fi
;;
*:srciface)
append "$var" "-i $value"
;;
1:pktsize)
value="$(echo "$value" | sed -e 's,-,:,g')"
add_insmod xt_length
append "$var" "-m length --length $value"
;;
1:limit)
add_insmod xt_limit
append "$var" "-m limit --limit $value"
;;
1:tcpflags)
case "$proto" in
tcp) append "$var" "-m tcp --tcp-flags ALL $value";;
*) unset $var; return 0;;
esac
;;
1:mark)
config_get class "${value##!}" classnr
[ -z "$class" ] && continue;
case "$value" in
!*) append "$var" "-m mark ! --mark $class/0x0f";;
*) append "$var" "-m mark --mark $class/0x0f";;
esac
;;
1:TOS)
add_insmod xt_DSCP
config_get TOS "$rule" 'TOS'
suffix="-j TOS --set-tos "${TOS:-"Normal-Service"}
;;
1:DSCP)
add_insmod xt_DSCP
config_get DSCP "$rule" 'DSCP'
[ -z "${DSCP%%[EBCA]*}" ] && set_value="--set-dscp-class $DSCP" \
|| set_value="--set-dscp $DSCP"
suffix="-j DSCP $set_value"
;;
esac
done
append "$var" "$suffix"
case "$ports:$proto" in
1:) parse_matching_rule "$var" "$section" "$options" "$prefix" "$suffix" "udp";;
esac
}
config_cb() {
option_cb() {
return 0
}
case "$1" in
interface)
config_set "$2" "classgroup" "Default"
config_set "$2" "upload" "128"
;;
classify|default|reclassify)
option_cb() {
append "CONFIG_${CONFIG_SECTION}_options" "$1"
}
;;
esac
}
qos_parse_config() {
config_get TYPE "$1" TYPE
case "$TYPE" in
interface)
config_get_bool enabled "$1" enabled 1
[ 1 -eq "$enabled" ] && {
config_get classgroup "$1" classgroup
config_set "$1" ifbdev "$C"
C=$(($C+1))
append INTERFACES "$1"
config_set "$classgroup" enabled 1
config_get device "$1" device
[ -z "$device" ] && {
device="$(find_ifname $1)"
[ -z "$device" ] && exit 1
config_set "$1" device "$device"
}
}
;;
classgroup) append CG "$1";;
classify|default|reclassify)
case "$TYPE" in
classify) var="ctrules";;
*) var="rules";;
esac
append "$var" "$1"
;;
esac
}
enum_classes() {
local c="0"
config_get classes "$1" classes
config_get default "$1" default
for class in $classes; do
c="$(($c + 1))"
config_set "${class}" classnr $c
case "$class" in
$default) class_default=$c;;
esac
done
class_default="${class_default:-$c}"
}
cls_var() {
local varname="$1"
local class="$2"
local name="$3"
local type="$4"
local default="$5"
local tmp tmp1 tmp2
config_get tmp1 "$class" "$name"
config_get tmp2 "${class}_${type}" "$name"
tmp="${tmp2:-$tmp1}"
tmp="${tmp:-$tmp2}"
export ${varname}="${tmp:-$default}"
}
tcrules() {
_dir=/usr/lib/qos
[ -e $_dir/tcrules.awk ] || _dir=.
echo "$cstr" | awk \
-v device="$dev" \
-v linespeed="$rate" \
-v direction="$dir" \
-f $_dir/tcrules.awk
}
start_interface() {
local iface="$1"
local num_ifb="$2"
config_get device "$iface" device
config_get_bool enabled "$iface" enabled 1
[ -z "$device" -o 1 -ne "$enabled" ] && {
return 1
}
config_get upload "$iface" upload
config_get_bool halfduplex "$iface" halfduplex
config_get download "$iface" download
config_get classgroup "$iface" classgroup
config_get_bool overhead "$iface" overhead 0
download="${download:-${halfduplex:+$upload}}"
enum_classes "$classgroup"
for dir in ${halfduplex:-up} ${download:+down}; do
case "$dir" in
up)
[ "$overhead" = 1 ] && upload=$(($upload * 98 / 100 - (15 * 128 / $upload)))
dev="$device"
rate="$upload"
dl_mode=""
prefix="cls"
;;
down)
[ "$(ls -d /proc/sys/net/ipv4/conf/ifb* 2>&- | wc -l)" -ne "$num_ifb" ] && add_insmod ifb numifbs="$num_ifb"
config_get ifbdev "$iface" ifbdev
[ "$overhead" = 1 ] && download=$(($download * 98 / 100 - (80 * 1024 / $download)))
dev="ifb$ifbdev"
rate="$download"
dl_mode=1
prefix="d_cls"
;;
*) continue;;
esac
cstr=
for class in $classes; do
cls_var pktsize "$class" packetsize $dir 1500
cls_var pktdelay "$class" packetdelay $dir 0
cls_var maxrate "$class" limitrate $dir 100
cls_var prio "$class" priority $dir 1
cls_var avgrate "$class" avgrate $dir 0
cls_var qdisc "$class" qdisc $dir ""
cls_var filter "$class" filter $dir ""
config_get classnr "$class" classnr
append cstr "$classnr:$prio:$avgrate:$pktsize:$pktdelay:$maxrate:$qdisc:$filter" "$N"
done
append ${prefix}q "$(tcrules)" "$N"
export dev_${dir}="ip link add ${dev} type ifb >&- 2>&-
ip link set $dev up >&- 2>&-
tc qdisc del dev $dev root >&- 2>&-
tc qdisc add dev $dev root handle 1: hfsc default ${class_default}0
tc class add dev $dev parent 1: classid 1:1 hfsc sc rate ${rate}kbit ul rate ${rate}kbit"
done
[ -n "$download" ] && {
add_insmod cls_u32
add_insmod em_u32
add_insmod act_connmark
add_insmod act_mirred
add_insmod sch_ingress
}
if [ -n "$halfduplex" ]; then
export dev_up="tc qdisc del dev $device root >&- 2>&-
tc qdisc add dev $device root handle 1: hfsc
tc filter add dev $device parent 1: prio 10 u32 match u32 0 0 flowid 1:1 action mirred egress redirect dev ifb$ifbdev"
elif [ -n "$download" ]; then
append dev_${dir} "tc qdisc del dev $device ingress >&- 2>&-
tc qdisc add dev $device ingress
tc filter add dev $device parent ffff: prio 1 u32 match u32 0 0 flowid 1:1 action connmark action mirred egress redirect dev ifb$ifbdev" "$N"
fi
add_insmod cls_fw
add_insmod sch_hfsc
cat <<EOF
${INSMOD:+$INSMOD$N}${dev_up:+$dev_up
$clsq
}${ifbdev:+$dev_down
$d_clsq
$d_clsl
$d_clsf
}
EOF
unset INSMOD clsq clsf clsl d_clsq d_clsl d_clsf dev_up dev_down
}
start_interfaces() {
local C="$1"
for iface in $INTERFACES; do
start_interface "$iface" "$C"
done
}
add_rules() {
local var="$1"
local rules="$2"
local prefix="$3"
for rule in $rules; do
unset iptrule
config_get target "$rule" target
config_get target "$target" classnr
config_get options "$rule" options
## If we want to override the TOS field, let's clear the DSCP field first.
[ ! -z "$(echo $options | grep 'TOS')" ] && {
s_options=${options%%TOS}
add_insmod xt_DSCP
parse_matching_rule iptrule "$rule" "$s_options" "$prefix" "-j DSCP --set-dscp 0"
append "$var" "$iptrule" "$N"
unset iptrule
}
target=$(($target | ($target << 4)))
parse_matching_rule iptrule "$rule" "$options" "$prefix" "-j MARK --set-mark $target/0xff"
append "$var" "$iptrule" "$N"
done
}
start_cg() {
local cg="$1"
local iptrules
local pktrules
local sizerules
enum_classes "$cg"
for command in $iptables; do
add_rules iptrules "$ctrules" "$command -w -t mangle -A qos_${cg}_ct"
done
config_get classes "$cg" classes
for class in $classes; do
config_get mark "$class" classnr
config_get maxsize "$class" maxsize
[ -z "$maxsize" -o -z "$mark" ] || {
add_insmod xt_length
for command in $iptables; do
append pktrules "$command -w -t mangle -A qos_${cg} -m mark --mark $mark/0x0f -m length --length $maxsize: -j MARK --set-mark 0/0xff" "$N"
done
}
done
for command in $iptables; do
add_rules pktrules "$rules" "$command -w -t mangle -A qos_${cg}"
done
for iface in $INTERFACES; do
config_get classgroup "$iface" classgroup
config_get device "$iface" device
config_get ifbdev "$iface" ifbdev
config_get upload "$iface" upload
config_get download "$iface" download
config_get halfduplex "$iface" halfduplex
download="${download:-${halfduplex:+$upload}}"
for command in $iptables; do
append up "$command -w -t mangle -A OUTPUT -o $device -j qos_${cg}" "$N"
append up "$command -w -t mangle -A FORWARD -o $device -j qos_${cg}" "$N"
done
done
cat <<EOF
$INSMOD
EOF
for command in $iptables; do
cat <<EOF
$command -w -t mangle -N qos_${cg}
$command -w -t mangle -N qos_${cg}_ct
EOF
done
cat <<EOF
${iptrules:+${iptrules}${N}}
EOF
for command in $iptables; do
cat <<EOF
$command -w -t mangle -A qos_${cg}_ct -j CONNMARK --save-mark --mask 0xff
$command -w -t mangle -A qos_${cg} -j CONNMARK --restore-mark --mask 0x0f
$command -w -t mangle -A qos_${cg} -m mark --mark 0/0x0f -j qos_${cg}_ct
EOF
done
cat <<EOF
$pktrules
EOF
for command in $iptables; do
cat <<EOF
$command -w -t mangle -A qos_${cg} -j CONNMARK --save-mark --mask 0xff
EOF
done
cat <<EOF
$up$N${down:+${down}$N}
EOF
unset INSMOD
}
start_firewall() {
add_insmod xt_multiport
add_insmod xt_connmark
stop_firewall
for group in $CG; do
start_cg $group
done
}
stop_firewall() {
# Builds up a list of iptables commands to flush the qos_* chains,
# remove rules referring to them, then delete them
# Print rules in the mangle table, like iptables-save
for command in $iptables; do
$command -w -t mangle -S |
# Find rules for the qos_* chains
grep -E '(^-N qos_|-j qos_)' |
# Exclude rules in qos_* chains (inter-qos_* refs)
grep -v '^-A qos_' |
# Replace -N with -X and hold, with -F and print
# Replace -A with -D
# Print held lines at the end (note leading newline)
sed -e '/^-N/{s/^-N/-X/;H;s/^-X/-F/}' \
-e 's/^-A/-D/' \
-e '${p;g}' |
# Make into proper iptables calls
# Note: awkward in previous call due to hold space usage
sed -n -e "s/^./${command} -w -t mangle &/p"
done
}
C="0"
INTERFACES=""
[ -e ./qos.conf ] && {
. ./qos.conf
config_cb
} || {
config_load qos
config_foreach qos_parse_config
}
C="0"
for iface in $INTERFACES; do
export C="$(($C + 1))"
done
[ -x /usr/sbin/ip6tables ] && {
iptables="ip6tables iptables"
} || {
iptables="iptables"
}
case "$1" in
all)
start_interfaces "$C"
start_firewall
;;
interface)
start_interface "$2" "$C"
;;
interfaces)
start_interfaces
;;
firewall)
case "$2" in
stop)
stop_firewall
;;
start|"")
start_firewall
;;
esac
;;
esac

View File

@@ -0,0 +1,106 @@
BEGIN {
dmax=100
if (!(linespeed > 0)) linespeed = 128
FS=":"
n = 0
}
($1 != "") {
n++
class[n] = $1
prio[n] = $2
avgrate[n] = ($3 * linespeed / 100)
pktsize[n] = $4
delay[n] = $5
maxrate[n] = ($6 * linespeed / 100)
qdisc[n] = $7
filter[n] = $8
}
END {
allocated = 0
maxdelay = 0
for (i = 1; i <= n; i++) {
# set defaults
if (!(pktsize[i] > 0)) pktsize[i] = 1500
if (!(prio[i] > 0)) prio[i] = 1
allocated += avgrate[i]
sum_prio += prio[i]
if ((avgrate[i] > 0) && !(delay[i] > 0)) {
sum_rtprio += prio[i]
}
}
# allocation of m1 in rt classes:
# sum(d * m1) must not exceed dmax * (linespeed - allocated)
dmax = 0
for (i = 1; i <= n; i++) {
if (avgrate[i] > 0) {
rtm2[i] = avgrate[i]
if (delay[i] > 0) {
d[i] = delay[i]
} else {
d[i] = 2 * pktsize[i] * 1000 / (linespeed * 1024)
if (d[i] > dmax) dmax = d[i]
}
}
}
ds_avail = dmax * (linespeed - allocated)
for (i = 1; i <= n; i++) {
lsm1[i] = 0
rtm1[i] = 0
lsm2[i] = linespeed * prio[i] / sum_prio
if ((avgrate[i] > 0) && (d[i] > 0)) {
if (!(delay[i] > 0)) {
ds = ds_avail * prio[i] / sum_rtprio
ds_avail -= ds
rtm1[i] = rtm2[i] + ds/d[i]
}
lsm1[i] = rtm1[i]
}
else {
d[i] = 0
}
}
# main qdisc
for (i = 1; i <= n; i++) {
printf "tc class add dev "device" parent 1:1 classid 1:"class[i]"0 hfsc"
if (rtm1[i] > 0) {
printf " rt m1 " int(rtm1[i]) "kbit d " int(d[i] * 1000) "us m2 " int(rtm2[i])"kbit"
}
printf " ls m1 " int(lsm1[i]) "kbit d " int(d[i] * 1000) "us m2 " int(lsm2[i]) "kbit"
print " ul rate " int(maxrate[i]) "kbit"
}
# leaf qdisc
avpkt = 1200
for (i = 1; i <= n; i++) {
print "tc qdisc add dev "device" parent 1:"class[i]"0 handle "class[i]"00: fq_codel limit 800 quantum 300 noecn"
}
# filter rule
for (i = 1; i <= n; i++) {
filter_cmd = "tc filter add dev "device" parent 1: prio %d handle %s fw flowid 1:%d0\n";
if (direction == "up") {
filter_1 = sprintf("0x%x0/0xf0", class[i])
filter_2 = sprintf("0x0%x/0x0f", class[i])
} else {
filter_1 = sprintf("0x0%x/0x0f", class[i])
filter_2 = sprintf("0x%x0/0xf0", class[i])
}
printf filter_cmd, class[i] * 2, filter_1, class[i]
printf filter_cmd, class[i] * 2 + 1, filter_2, class[i]
filterc=1
if (filter[i] != "") {
print " tc filter add dev "device" parent "class[i]"00: handle "filterc"0 "filter[i]
filterc=filterc+1
}
}
}

View File

@@ -0,0 +1,45 @@
#
# 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:=soloscli
PKG_VERSION:=1.04
PKG_RELEASE:=3
PKG_SOURCE:=solos-pci-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=@SF/openadsl
PKG_HASH:=6379e6970a5c97fd5a223d024138ebb71b15d70e2ad1fe9da09edc5b2d760e1d
PKG_LICENSE:=GPL-2.0
PKG_BUILD_DIR:=$(BUILD_DIR)/solos-pci-$(PKG_VERSION)
PKG_BUILD_PARALLEL:=1
include $(INCLUDE_DIR)/package.mk
define Package/soloscli
SECTION:=net
CATEGORY:=Network
TITLE:=Configuration utility for Solos ADSL2+ modems
DEPENDS:=+kmod-solos-pci
URL:=http://sourceforge.net/projects/openadsl
endef
define Package/soloscli/description
This package contains the soloscli utility
for interrogating Traverse Technologies' Solos ADSL2+ modems.
endef
define Package/soloscli/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/soloscli/soloscli $(1)/usr/bin/
$(INSTALL_BIN) ./files/solos-log-stats $(1)/usr/bin/
$(INSTALL_DIR) $(1)/etc/hotplug.d/atm
$(INSTALL_CONF) ./files/etc/hotplug.d/atm/15-solos-init $(1)/etc/hotplug.d/atm/
endef
$(eval $(call BuildPackage,soloscli))

View File

@@ -0,0 +1,26 @@
#!/bin/sh
dialog() {
local tag="$(echo "$1" | cut -d= -f1)"
local value="$(echo "$1" | cut -d= -f2-)"
local response
response="$(soloscli -s "$port" "$tag" "$value")"
[ $? -ne 0 ] && {
logger "soloscli($port): $tag '$value' returns $response"
}
}
if [ "$ACTION" = "add" ]; then
include /lib/network
scan_interfaces
case $DEVICENAME in
solos-pci[0-3])
port="${DEVICENAME#solos-pci}"
device="solos${port}"
config_list_foreach wan "$device" dialog
;;
esac
fi

View File

@@ -0,0 +1,13 @@
uci batch <<__EOF__
delete network.wan.solos0
add_list network.wan.solos0="ActivateLine=Abort"
add_list network.wan.solos0="Retrain=EnableAll"
add_list network.wan.solos0="DetectNoise=Enable"
add_list network.wan.solos0="BisMCapability=Disable"
add_list network.wan.solos0="BisACapability=Disable"
add_list network.wan.solos0="ActivateLine=Start"
commit network
__EOF__

View File

@@ -0,0 +1,19 @@
#!/bin/sh
cd /sys/class/atm/ || exit 1
for PORT in solos-pci* ; do
RXRATE=`cat $PORT/parameters/RxBitRate`
TXRATE=`cat $PORT/parameters/TxBitRate`
RXSNR=`cat $PORT/parameters/LocalSNRMargin | sed "s/ dB//"`
TXSNR=`cat $PORT/parameters/RemoteSNRMargin | sed "s/ dB//"`
RXERR=`cat $PORT/parameters/RSUnCorrectedErrorsDn`
TXERR=`cat $PORT/parameters/RSUnCorrectedErrorsUp`
RXFEC=`cat $PORT/parameters/RSCorrectedErrorsDn`
TXFEC=`cat $PORT/parameters/RSCorrectedErrorsUp`
echo "$RXRATE $RXSNR $RXERR $RXFEC / $TXRATE $TXSNR $TXERR $TXFEC" |
logger -t $PORT
done

View File

@@ -0,0 +1,11 @@
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ else
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
-all: soloscli driver
+all: soloscli
soloscli: soloscli/soloscli

View File

@@ -0,0 +1,12 @@
--- a/soloscli/Makefile
+++ b/soloscli/Makefile
@@ -4,9 +4,6 @@
# Last Mod: 2009-06-16
#
-CC=gcc
-CFLAGS=-Wall
-
soloscli: soloscli.c soloscli.h
clean:

View File

@@ -0,0 +1,57 @@
#
# Copyright (C) 2008-2010 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=swconfig
PKG_RELEASE:=12
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/kernel.mk
define Package/swconfig
SECTION:=base
CATEGORY:=Base system
DEPENDS:=+libuci +libnl-tiny
TITLE:=Switch configuration utility
endef
TARGET_CFLAGS += -flto
TARGET_LDFLAGS += -flto=jobserver
TARGET_CPPFLAGS := \
-D_GNU_SOURCE \
-I$(STAGING_DIR)/usr/include/libnl-tiny \
-I$(PKG_BUILD_DIR) \
$(TARGET_CPPFLAGS) \
-I$(LINUX_DIR)/user_headers/include
define Build/Compile
CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
$(MAKE) -C $(PKG_BUILD_DIR) \
$(TARGET_CONFIGURE_OPTS) \
LIBS="$(TARGET_LDFLAGS) -lnl-tiny -lm -luci -lubox"
endef
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/include
$(CP) $(PKG_BUILD_DIR)/swlib.h $(1)/usr/include/
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_BUILD_DIR)/libsw.a $(1)/usr/lib/
endef
define Package/swconfig/install
$(INSTALL_DIR) $(1)/sbin $(1)/lib/network
$(INSTALL_BIN) $(PKG_BUILD_DIR)/swconfig $(1)/sbin/swconfig
$(INSTALL_DATA) ./files/switch.sh $(1)/lib/network/
endef
$(eval $(call BuildPackage,swconfig))

View File

@@ -0,0 +1,15 @@
#!/bin/sh
# Copyright (C) 2009 OpenWrt.org
setup_switch_dev() {
local name
config_get name "$1" name
name="${name:-$1}"
[ -d "/sys/class/net/$name" ] && ip link set dev "$name" up
swconfig dev "$name" load network
}
setup_switch() {
config_load network
config_foreach setup_switch_dev switch
}

View File

@@ -0,0 +1,16 @@
ifndef CFLAGS
CFLAGS = -O2 -g -I ../src
endif
LIBS=-lnl -lnl-genl
all: swconfig
%.o: %.c
$(CC) $(CFLAGS) -fPIC -c -o $@ $^
libsw.a: swlib.o
$(AR) rcu $@ swlib.o
$(RANLIB) $@
swconfig: libsw.a cli.o uci.o
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -L./ -lsw

View File

@@ -0,0 +1,387 @@
/*
* swconfig.c: Switch configuration utility
*
* Copyright (C) 2008 Felix Fietkau <nbd@nbd.name>
* Copyright (C) 2010 Martin Mares <mj@ucw.cz>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundatio.
*
* 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.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <stdint.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <uci.h>
#include <linux/types.h>
#include <linux/netlink.h>
#include <linux/genetlink.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <linux/switch.h>
#include "swlib.h"
enum {
CMD_NONE,
CMD_GET,
CMD_SET,
CMD_LOAD,
CMD_HELP,
CMD_SHOW,
CMD_PORTMAP,
};
static void
print_attrs(const struct switch_attr *attr)
{
int i = 0;
while (attr) {
const char *type;
switch(attr->type) {
case SWITCH_TYPE_INT:
type = "int";
break;
case SWITCH_TYPE_STRING:
type = "string";
break;
case SWITCH_TYPE_PORTS:
type = "ports";
break;
case SWITCH_TYPE_NOVAL:
type = "none";
break;
default:
type = "unknown";
break;
}
printf("\tAttribute %d (%s): %s (%s)\n", ++i, type, attr->name, attr->description);
attr = attr->next;
}
}
static void
list_attributes(struct switch_dev *dev)
{
printf("%s: %s(%s), ports: %d (cpu @ %d), vlans: %d\n", dev->dev_name, dev->alias, dev->name, dev->ports, dev->cpu_port, dev->vlans);
printf(" --switch\n");
print_attrs(dev->ops);
printf(" --vlan\n");
print_attrs(dev->vlan_ops);
printf(" --port\n");
print_attrs(dev->port_ops);
}
static const char *
speed_str(int speed)
{
switch (speed) {
case 10:
return "10baseT";
case 100:
return "100baseT";
case 1000:
return "1000baseT";
default:
break;
}
return "unknown";
}
static void
print_attr_val(const struct switch_attr *attr, const struct switch_val *val)
{
struct switch_port_link *link;
int i;
switch (attr->type) {
case SWITCH_TYPE_INT:
printf("%d", val->value.i);
break;
case SWITCH_TYPE_STRING:
printf("%s", val->value.s);
break;
case SWITCH_TYPE_PORTS:
for(i = 0; i < val->len; i++) {
printf("%d%s ",
val->value.ports[i].id,
(val->value.ports[i].flags &
SWLIB_PORT_FLAG_TAGGED) ? "t" : "");
}
break;
case SWITCH_TYPE_LINK:
link = val->value.link;
if (link->link)
printf("port:%d link:up speed:%s %s-duplex %s%s%s%s%s",
val->port_vlan,
speed_str(link->speed),
link->duplex ? "full" : "half",
link->tx_flow ? "txflow " : "",
link->rx_flow ? "rxflow " : "",
link->eee & SWLIB_LINK_FLAG_EEE_100BASET ? "eee100 " : "",
link->eee & SWLIB_LINK_FLAG_EEE_1000BASET ? "eee1000 " : "",
link->aneg ? "auto" : "");
else
printf("port:%d link:down", val->port_vlan);
break;
default:
printf("?unknown-type?");
}
}
static void
show_attrs(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
{
while (attr) {
if (attr->type != SWITCH_TYPE_NOVAL) {
printf("\t%s: ", attr->name);
if (swlib_get_attr(dev, attr, val) < 0)
printf("???");
else
print_attr_val(attr, val);
putchar('\n');
}
attr = attr->next;
}
}
static void
show_global(struct switch_dev *dev)
{
struct switch_val val;
printf("Global attributes:\n");
show_attrs(dev, dev->ops, &val);
}
static void
show_port(struct switch_dev *dev, int port)
{
struct switch_val val;
printf("Port %d:\n", port);
val.port_vlan = port;
show_attrs(dev, dev->port_ops, &val);
}
static void
show_vlan(struct switch_dev *dev, int vlan, bool all)
{
struct switch_val val;
struct switch_attr *attr;
val.port_vlan = vlan;
if (all) {
attr = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_VLAN, "ports");
if (swlib_get_attr(dev, attr, &val) < 0)
return;
if (!val.len)
return;
}
printf("VLAN %d:\n", vlan);
show_attrs(dev, dev->vlan_ops, &val);
}
static void
print_usage(void)
{
printf("swconfig list\n");
printf("swconfig dev <dev> [port <port>|vlan <vlan>] (help|set <key> <value>|get <key>|load <config>|show)\n");
exit(1);
}
static void
swconfig_load_uci(struct switch_dev *dev, const char *name)
{
struct uci_context *ctx;
struct uci_package *p = NULL;
int ret = -1;
ctx = uci_alloc_context();
if (!ctx)
return;
uci_load(ctx, name, &p);
if (!p) {
uci_perror(ctx, "Failed to load config file: ");
goto out;
}
ret = swlib_apply_from_uci(dev, p);
if (ret < 0)
fprintf(stderr, "Failed to apply configuration for switch '%s'\n", dev->dev_name);
out:
uci_free_context(ctx);
exit(ret);
}
int main(int argc, char **argv)
{
int retval = 0;
struct switch_dev *dev;
struct switch_attr *a;
struct switch_val val;
int i;
int cmd = CMD_NONE;
char *cdev = NULL;
int cport = -1;
int cvlan = -1;
char *ckey = NULL;
char *cvalue = NULL;
char *csegment = NULL;
if((argc == 2) && !strcmp(argv[1], "list")) {
swlib_list();
return 0;
}
if(argc < 4)
print_usage();
if(strcmp(argv[1], "dev"))
print_usage();
cdev = argv[2];
for(i = 3; i < argc; i++)
{
char *arg = argv[i];
if (cmd != CMD_NONE) {
print_usage();
} else if (!strcmp(arg, "port") && i+1 < argc) {
cport = atoi(argv[++i]);
} else if (!strcmp(arg, "vlan") && i+1 < argc) {
cvlan = atoi(argv[++i]);
} else if (!strcmp(arg, "help")) {
cmd = CMD_HELP;
} else if (!strcmp(arg, "set") && i+1 < argc) {
cmd = CMD_SET;
ckey = argv[++i];
if (i+1 < argc)
cvalue = argv[++i];
} else if (!strcmp(arg, "get") && i+1 < argc) {
cmd = CMD_GET;
ckey = argv[++i];
} else if (!strcmp(arg, "load") && i+1 < argc) {
if ((cport >= 0) || (cvlan >= 0))
print_usage();
cmd = CMD_LOAD;
ckey = argv[++i];
} else if (!strcmp(arg, "portmap")) {
if (i + 1 < argc)
csegment = argv[++i];
cmd = CMD_PORTMAP;
} else if (!strcmp(arg, "show")) {
cmd = CMD_SHOW;
} else {
print_usage();
}
}
if (cmd == CMD_NONE)
print_usage();
if (cport > -1 && cvlan > -1)
print_usage();
dev = swlib_connect(cdev);
if (!dev) {
fprintf(stderr, "Failed to connect to the switch. Use the \"list\" command to see which switches are available.\n");
return 1;
}
swlib_scan(dev);
if (cmd == CMD_GET || cmd == CMD_SET) {
if(cport > -1)
a = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_PORT, ckey);
else if(cvlan > -1)
a = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_VLAN, ckey);
else
a = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_GLOBAL, ckey);
if(!a)
{
fprintf(stderr, "Unknown attribute \"%s\"\n", ckey);
retval = -1;
goto out;
}
}
switch(cmd)
{
case CMD_SET:
if ((a->type != SWITCH_TYPE_NOVAL) &&
(cvalue == NULL))
print_usage();
if(cvlan > -1)
cport = cvlan;
retval = swlib_set_attr_string(dev, a, cport, cvalue);
if (retval < 0)
{
nl_perror(-retval, "Failed to set attribute");
goto out;
}
break;
case CMD_GET:
if(cvlan > -1)
val.port_vlan = cvlan;
if(cport > -1)
val.port_vlan = cport;
retval = swlib_get_attr(dev, a, &val);
if (retval < 0)
{
nl_perror(-retval, "Failed to get attribute");
goto out;
}
print_attr_val(a, &val);
putchar('\n');
break;
case CMD_LOAD:
swconfig_load_uci(dev, ckey);
break;
case CMD_HELP:
list_attributes(dev);
break;
case CMD_PORTMAP:
swlib_print_portmap(dev, csegment);
break;
case CMD_SHOW:
if (cport >= 0 || cvlan >= 0) {
if (cport >= 0)
show_port(dev, cport);
else
show_vlan(dev, cvlan, false);
} else {
show_global(dev);
for (i=0; i < dev->ports; i++)
show_port(dev, i);
for (i=0; i < dev->vlans; i++)
show_vlan(dev, i, true);
}
break;
}
out:
swlib_free_all(dev);
return retval;
}

View File

@@ -0,0 +1,924 @@
/*
* swlib.c: Switch configuration API (user space part)
*
* Copyright (C) 2008 Felix Fietkau <nbd@nbd.name>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* 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.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <inttypes.h>
#include <errno.h>
#include <stdint.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/switch.h>
#include "swlib.h"
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
//#define DEBUG 1
#ifdef DEBUG
#define DPRINTF(fmt, ...) fprintf(stderr, "%s(%d): " fmt, __func__, __LINE__, ##__VA_ARGS__)
#else
#define DPRINTF(fmt, ...) do {} while (0)
#endif
static struct nl_sock *handle;
static struct nl_cache *cache;
static struct genl_family *family;
static struct nlattr *tb[SWITCH_ATTR_MAX + 1];
static int refcount = 0;
static struct nla_policy port_policy[SWITCH_ATTR_MAX] = {
[SWITCH_PORT_ID] = { .type = NLA_U32 },
[SWITCH_PORT_FLAG_TAGGED] = { .type = NLA_FLAG },
};
static struct nla_policy portmap_policy[SWITCH_PORTMAP_MAX] = {
[SWITCH_PORTMAP_SEGMENT] = { .type = NLA_STRING },
[SWITCH_PORTMAP_VIRT] = { .type = NLA_U32 },
};
static struct nla_policy link_policy[SWITCH_LINK_ATTR_MAX] = {
[SWITCH_LINK_FLAG_LINK] = { .type = NLA_FLAG },
[SWITCH_LINK_FLAG_DUPLEX] = { .type = NLA_FLAG },
[SWITCH_LINK_FLAG_ANEG] = { .type = NLA_FLAG },
[SWITCH_LINK_SPEED] = { .type = NLA_U32 },
[SWITCH_LINK_FLAG_EEE_100BASET] = { .type = NLA_FLAG },
[SWITCH_LINK_FLAG_EEE_1000BASET] = { .type = NLA_FLAG },
};
static inline void *
swlib_alloc(size_t size)
{
void *ptr;
ptr = malloc(size);
if (!ptr)
goto done;
memset(ptr, 0, size);
done:
return ptr;
}
static int
wait_handler(struct nl_msg *msg, void *arg)
{
int *finished = arg;
*finished = 1;
return NL_STOP;
}
/* helper function for performing netlink requests */
static int
swlib_call(int cmd, int (*call)(struct nl_msg *, void *),
int (*data)(struct nl_msg *, void *), void *arg)
{
struct nl_msg *msg;
struct nl_cb *cb = NULL;
int finished;
int flags = 0;
int err = 0;
msg = nlmsg_alloc();
if (!msg) {
fprintf(stderr, "Out of memory!\n");
exit(1);
}
if (!data)
flags |= NLM_F_DUMP;
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, genl_family_get_id(family), 0, flags, cmd, 0);
if (data) {
err = data(msg, arg);
if (err < 0)
goto nla_put_failure;
}
cb = nl_cb_alloc(NL_CB_CUSTOM);
if (!cb) {
fprintf(stderr, "nl_cb_alloc failed.\n");
exit(1);
}
err = nl_send_auto_complete(handle, msg);
if (err < 0) {
fprintf(stderr, "nl_send_auto_complete failed: %d\n", err);
goto out;
}
finished = 0;
if (call)
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, call, arg);
if (data)
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, wait_handler, &finished);
else
nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, wait_handler, &finished);
err = nl_recvmsgs(handle, cb);
if (err < 0) {
goto out;
}
if (!finished)
err = nl_wait_for_ack(handle);
out:
if (cb)
nl_cb_put(cb);
nla_put_failure:
nlmsg_free(msg);
return err;
}
static int
send_attr(struct nl_msg *msg, void *arg)
{
struct switch_val *val = arg;
struct switch_attr *attr = val->attr;
NLA_PUT_U32(msg, SWITCH_ATTR_ID, attr->dev->id);
NLA_PUT_U32(msg, SWITCH_ATTR_OP_ID, attr->id);
switch(attr->atype) {
case SWLIB_ATTR_GROUP_PORT:
NLA_PUT_U32(msg, SWITCH_ATTR_OP_PORT, val->port_vlan);
break;
case SWLIB_ATTR_GROUP_VLAN:
NLA_PUT_U32(msg, SWITCH_ATTR_OP_VLAN, val->port_vlan);
break;
default:
break;
}
return 0;
nla_put_failure:
return -1;
}
static int
store_port_val(struct nl_msg *msg, struct nlattr *nla, struct switch_val *val)
{
struct nlattr *p;
int ports = val->attr->dev->ports;
int err = 0;
int remaining;
if (!val->value.ports)
val->value.ports = malloc(sizeof(struct switch_port) * ports);
nla_for_each_nested(p, nla, remaining) {
struct nlattr *tb[SWITCH_PORT_ATTR_MAX+1];
struct switch_port *port;
if (val->len >= ports)
break;
err = nla_parse_nested(tb, SWITCH_PORT_ATTR_MAX, p, port_policy);
if (err < 0)
goto out;
if (!tb[SWITCH_PORT_ID])
continue;
port = &val->value.ports[val->len];
port->id = nla_get_u32(tb[SWITCH_PORT_ID]);
port->flags = 0;
if (tb[SWITCH_PORT_FLAG_TAGGED])
port->flags |= SWLIB_PORT_FLAG_TAGGED;
val->len++;
}
out:
return err;
}
static int
store_link_val(struct nl_msg *msg, struct nlattr *nla, struct switch_val *val)
{
struct nlattr *tb[SWITCH_LINK_ATTR_MAX + 1];
struct switch_port_link *link;
int err = 0;
if (!val->value.link)
val->value.link = malloc(sizeof(struct switch_port_link));
err = nla_parse_nested(tb, SWITCH_LINK_ATTR_MAX, nla, link_policy);
if (err < 0)
goto out;
link = val->value.link;
link->link = !!tb[SWITCH_LINK_FLAG_LINK];
link->duplex = !!tb[SWITCH_LINK_FLAG_DUPLEX];
link->aneg = !!tb[SWITCH_LINK_FLAG_ANEG];
link->tx_flow = !!tb[SWITCH_LINK_FLAG_TX_FLOW];
link->rx_flow = !!tb[SWITCH_LINK_FLAG_RX_FLOW];
link->speed = nla_get_u32(tb[SWITCH_LINK_SPEED]);
link->eee = 0;
if (tb[SWITCH_LINK_FLAG_EEE_100BASET])
link->eee |= SWLIB_LINK_FLAG_EEE_100BASET;
if (tb[SWITCH_LINK_FLAG_EEE_1000BASET])
link->eee |= SWLIB_LINK_FLAG_EEE_1000BASET;
out:
return err;
}
static int
store_val(struct nl_msg *msg, void *arg)
{
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct switch_val *val = arg;
if (!val)
goto error;
if (nla_parse(tb, SWITCH_ATTR_MAX - 1, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL) < 0) {
goto error;
}
if (tb[SWITCH_ATTR_OP_VALUE_INT])
val->value.i = nla_get_u32(tb[SWITCH_ATTR_OP_VALUE_INT]);
else if (tb[SWITCH_ATTR_OP_VALUE_STR])
val->value.s = strdup(nla_get_string(tb[SWITCH_ATTR_OP_VALUE_STR]));
else if (tb[SWITCH_ATTR_OP_VALUE_PORTS])
val->err = store_port_val(msg, tb[SWITCH_ATTR_OP_VALUE_PORTS], val);
else if (tb[SWITCH_ATTR_OP_VALUE_LINK])
val->err = store_link_val(msg, tb[SWITCH_ATTR_OP_VALUE_LINK], val);
val->err = 0;
return 0;
error:
return NL_SKIP;
}
int
swlib_get_attr(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
{
int cmd;
int err;
switch(attr->atype) {
case SWLIB_ATTR_GROUP_GLOBAL:
cmd = SWITCH_CMD_GET_GLOBAL;
break;
case SWLIB_ATTR_GROUP_PORT:
cmd = SWITCH_CMD_GET_PORT;
break;
case SWLIB_ATTR_GROUP_VLAN:
cmd = SWITCH_CMD_GET_VLAN;
break;
default:
return -EINVAL;
}
memset(&val->value, 0, sizeof(val->value));
val->len = 0;
val->attr = attr;
val->err = -EINVAL;
err = swlib_call(cmd, store_val, send_attr, val);
if (!err)
err = val->err;
return err;
}
static int
send_attr_ports(struct nl_msg *msg, struct switch_val *val)
{
struct nlattr *n;
int i;
/* TODO implement multipart? */
if (val->len == 0)
goto done;
n = nla_nest_start(msg, SWITCH_ATTR_OP_VALUE_PORTS);
if (!n)
goto nla_put_failure;
for (i = 0; i < val->len; i++) {
struct switch_port *port = &val->value.ports[i];
struct nlattr *np;
np = nla_nest_start(msg, SWITCH_ATTR_PORT);
if (!np)
goto nla_put_failure;
NLA_PUT_U32(msg, SWITCH_PORT_ID, port->id);
if (port->flags & SWLIB_PORT_FLAG_TAGGED)
NLA_PUT_FLAG(msg, SWITCH_PORT_FLAG_TAGGED);
nla_nest_end(msg, np);
}
nla_nest_end(msg, n);
done:
return 0;
nla_put_failure:
return -1;
}
static int
send_attr_link(struct nl_msg *msg, struct switch_val *val)
{
struct switch_port_link *link = val->value.link;
struct nlattr *n;
n = nla_nest_start(msg, SWITCH_ATTR_OP_VALUE_LINK);
if (!n)
goto nla_put_failure;
if (link->duplex)
NLA_PUT_FLAG(msg, SWITCH_LINK_FLAG_DUPLEX);
if (link->aneg)
NLA_PUT_FLAG(msg, SWITCH_LINK_FLAG_ANEG);
NLA_PUT_U32(msg, SWITCH_LINK_SPEED, link->speed);
nla_nest_end(msg, n);
return 0;
nla_put_failure:
return -1;
}
static int
send_attr_val(struct nl_msg *msg, void *arg)
{
struct switch_val *val = arg;
struct switch_attr *attr = val->attr;
if (send_attr(msg, arg))
goto nla_put_failure;
switch(attr->type) {
case SWITCH_TYPE_NOVAL:
break;
case SWITCH_TYPE_INT:
NLA_PUT_U32(msg, SWITCH_ATTR_OP_VALUE_INT, val->value.i);
break;
case SWITCH_TYPE_STRING:
if (!val->value.s)
goto nla_put_failure;
NLA_PUT_STRING(msg, SWITCH_ATTR_OP_VALUE_STR, val->value.s);
break;
case SWITCH_TYPE_PORTS:
if (send_attr_ports(msg, val) < 0)
goto nla_put_failure;
break;
case SWITCH_TYPE_LINK:
if (send_attr_link(msg, val))
goto nla_put_failure;
break;
default:
goto nla_put_failure;
}
return 0;
nla_put_failure:
return -1;
}
int
swlib_set_attr(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
{
int cmd;
switch(attr->atype) {
case SWLIB_ATTR_GROUP_GLOBAL:
cmd = SWITCH_CMD_SET_GLOBAL;
break;
case SWLIB_ATTR_GROUP_PORT:
cmd = SWITCH_CMD_SET_PORT;
break;
case SWLIB_ATTR_GROUP_VLAN:
cmd = SWITCH_CMD_SET_VLAN;
break;
default:
return -EINVAL;
}
val->attr = attr;
return swlib_call(cmd, NULL, send_attr_val, val);
}
enum {
CMD_NONE,
CMD_DUPLEX,
CMD_ANEG,
CMD_SPEED,
};
int swlib_set_attr_string(struct switch_dev *dev, struct switch_attr *a, int port_vlan, const char *str)
{
struct switch_port *ports;
struct switch_port_link *link;
struct switch_val val;
char *ptr;
int cmd = CMD_NONE;
memset(&val, 0, sizeof(val));
val.port_vlan = port_vlan;
switch(a->type) {
case SWITCH_TYPE_INT:
val.value.i = atoi(str);
break;
case SWITCH_TYPE_STRING:
val.value.s = (char *)str;
break;
case SWITCH_TYPE_PORTS:
ports = alloca(sizeof(struct switch_port) * dev->ports);
memset(ports, 0, sizeof(struct switch_port) * dev->ports);
val.len = 0;
ptr = (char *)str;
while(ptr && *ptr)
{
while(*ptr && isspace(*ptr))
ptr++;
if (!*ptr)
break;
if (!isdigit(*ptr))
return -1;
if (val.len >= dev->ports)
return -1;
ports[val.len].flags = 0;
ports[val.len].id = strtoul(ptr, &ptr, 10);
while(*ptr && !isspace(*ptr)) {
if (*ptr == 't')
ports[val.len].flags |= SWLIB_PORT_FLAG_TAGGED;
else
return -1;
ptr++;
}
if (*ptr)
ptr++;
val.len++;
}
val.value.ports = ports;
break;
case SWITCH_TYPE_LINK:
link = malloc(sizeof(struct switch_port_link));
memset(link, 0, sizeof(struct switch_port_link));
ptr = (char *)str;
for (ptr = strtok(ptr," "); ptr; ptr = strtok(NULL, " ")) {
switch (cmd) {
case CMD_NONE:
if (!strcmp(ptr, "duplex"))
cmd = CMD_DUPLEX;
else if (!strcmp(ptr, "autoneg"))
cmd = CMD_ANEG;
else if (!strcmp(ptr, "speed"))
cmd = CMD_SPEED;
else
fprintf(stderr, "Unsupported option %s\n", ptr);
break;
case CMD_DUPLEX:
if (!strcmp(ptr, "half"))
link->duplex = 0;
else if (!strcmp(ptr, "full"))
link->duplex = 1;
else
fprintf(stderr, "Unsupported value %s\n", ptr);
cmd = CMD_NONE;
break;
case CMD_ANEG:
if (!strcmp(ptr, "on"))
link->aneg = 1;
else if (!strcmp(ptr, "off"))
link->aneg = 0;
else
fprintf(stderr, "Unsupported value %s\n", ptr);
cmd = CMD_NONE;
break;
case CMD_SPEED:
link->speed = atoi(ptr);
cmd = CMD_NONE;
break;
}
}
val.value.link = link;
break;
case SWITCH_TYPE_NOVAL:
if (str && !strcmp(str, "0"))
return 0;
break;
default:
return -1;
}
return swlib_set_attr(dev, a, &val);
}
struct attrlist_arg {
int id;
int atype;
struct switch_dev *dev;
struct switch_attr *prev;
struct switch_attr **head;
};
static int
add_id(struct nl_msg *msg, void *arg)
{
struct attrlist_arg *l = arg;
NLA_PUT_U32(msg, SWITCH_ATTR_ID, l->id);
return 0;
nla_put_failure:
return -1;
}
static int
add_attr(struct nl_msg *msg, void *ptr)
{
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct attrlist_arg *arg = ptr;
struct switch_attr *new;
if (nla_parse(tb, SWITCH_ATTR_MAX - 1, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL) < 0)
goto done;
new = swlib_alloc(sizeof(struct switch_attr));
if (!new)
goto done;
new->dev = arg->dev;
new->atype = arg->atype;
if (arg->prev) {
arg->prev->next = new;
} else {
arg->prev = *arg->head;
}
*arg->head = new;
arg->head = &new->next;
if (tb[SWITCH_ATTR_OP_ID])
new->id = nla_get_u32(tb[SWITCH_ATTR_OP_ID]);
if (tb[SWITCH_ATTR_OP_TYPE])
new->type = nla_get_u32(tb[SWITCH_ATTR_OP_TYPE]);
if (tb[SWITCH_ATTR_OP_NAME])
new->name = strdup(nla_get_string(tb[SWITCH_ATTR_OP_NAME]));
if (tb[SWITCH_ATTR_OP_DESCRIPTION])
new->description = strdup(nla_get_string(tb[SWITCH_ATTR_OP_DESCRIPTION]));
done:
return NL_SKIP;
}
int
swlib_scan(struct switch_dev *dev)
{
struct attrlist_arg arg;
if (dev->ops || dev->port_ops || dev->vlan_ops)
return 0;
arg.atype = SWLIB_ATTR_GROUP_GLOBAL;
arg.dev = dev;
arg.id = dev->id;
arg.prev = NULL;
arg.head = &dev->ops;
swlib_call(SWITCH_CMD_LIST_GLOBAL, add_attr, add_id, &arg);
arg.atype = SWLIB_ATTR_GROUP_PORT;
arg.prev = NULL;
arg.head = &dev->port_ops;
swlib_call(SWITCH_CMD_LIST_PORT, add_attr, add_id, &arg);
arg.atype = SWLIB_ATTR_GROUP_VLAN;
arg.prev = NULL;
arg.head = &dev->vlan_ops;
swlib_call(SWITCH_CMD_LIST_VLAN, add_attr, add_id, &arg);
return 0;
}
struct switch_attr *swlib_lookup_attr(struct switch_dev *dev,
enum swlib_attr_group atype, const char *name)
{
struct switch_attr *head;
if (!name || !dev)
return NULL;
switch(atype) {
case SWLIB_ATTR_GROUP_GLOBAL:
head = dev->ops;
break;
case SWLIB_ATTR_GROUP_PORT:
head = dev->port_ops;
break;
case SWLIB_ATTR_GROUP_VLAN:
head = dev->vlan_ops;
break;
}
while(head) {
if (!strcmp(name, head->name))
return head;
head = head->next;
}
return NULL;
}
static void
swlib_priv_free(void)
{
if (family)
nl_object_put((struct nl_object*)family);
if (cache)
nl_cache_free(cache);
if (handle)
nl_socket_free(handle);
family = NULL;
handle = NULL;
cache = NULL;
}
static int
swlib_priv_init(void)
{
int ret;
handle = nl_socket_alloc();
if (!handle) {
DPRINTF("Failed to create handle\n");
goto err;
}
if (genl_connect(handle)) {
DPRINTF("Failed to connect to generic netlink\n");
goto err;
}
ret = genl_ctrl_alloc_cache(handle, &cache);
if (ret < 0) {
DPRINTF("Failed to allocate netlink cache\n");
goto err;
}
family = genl_ctrl_search_by_name(cache, "switch");
if (!family) {
DPRINTF("Switch API not present\n");
goto err;
}
return 0;
err:
swlib_priv_free();
return -EINVAL;
}
struct swlib_scan_arg {
const char *name;
struct switch_dev *head;
struct switch_dev *ptr;
};
static int
add_port_map(struct switch_dev *dev, struct nlattr *nla)
{
struct nlattr *p;
int err = 0, idx = 0;
int remaining;
dev->maps = malloc(sizeof(struct switch_portmap) * dev->ports);
if (!dev->maps)
return -1;
memset(dev->maps, 0, sizeof(struct switch_portmap) * dev->ports);
nla_for_each_nested(p, nla, remaining) {
struct nlattr *tb[SWITCH_PORTMAP_MAX+1];
if (idx >= dev->ports)
continue;
err = nla_parse_nested(tb, SWITCH_PORTMAP_MAX, p, portmap_policy);
if (err < 0)
continue;
if (tb[SWITCH_PORTMAP_SEGMENT] && tb[SWITCH_PORTMAP_VIRT]) {
dev->maps[idx].segment = strdup(nla_get_string(tb[SWITCH_PORTMAP_SEGMENT]));
dev->maps[idx].virt = nla_get_u32(tb[SWITCH_PORTMAP_VIRT]);
}
idx++;
}
out:
return err;
}
static int
add_switch(struct nl_msg *msg, void *arg)
{
struct swlib_scan_arg *sa = arg;
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct switch_dev *dev;
const char *name;
const char *alias;
if (nla_parse(tb, SWITCH_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0)
goto done;
if (!tb[SWITCH_ATTR_DEV_NAME])
goto done;
name = nla_get_string(tb[SWITCH_ATTR_DEV_NAME]);
alias = nla_get_string(tb[SWITCH_ATTR_ALIAS]);
if (sa->name && (strcmp(name, sa->name) != 0) && (strcmp(alias, sa->name) != 0))
goto done;
dev = swlib_alloc(sizeof(struct switch_dev));
if (!dev)
goto done;
strncpy(dev->dev_name, name, IFNAMSIZ - 1);
dev->alias = strdup(alias);
if (tb[SWITCH_ATTR_ID])
dev->id = nla_get_u32(tb[SWITCH_ATTR_ID]);
if (tb[SWITCH_ATTR_NAME])
dev->name = strdup(nla_get_string(tb[SWITCH_ATTR_NAME]));
if (tb[SWITCH_ATTR_PORTS])
dev->ports = nla_get_u32(tb[SWITCH_ATTR_PORTS]);
if (tb[SWITCH_ATTR_VLANS])
dev->vlans = nla_get_u32(tb[SWITCH_ATTR_VLANS]);
if (tb[SWITCH_ATTR_CPU_PORT])
dev->cpu_port = nla_get_u32(tb[SWITCH_ATTR_CPU_PORT]);
if (tb[SWITCH_ATTR_PORTMAP])
add_port_map(dev, tb[SWITCH_ATTR_PORTMAP]);
if (!sa->head) {
sa->head = dev;
sa->ptr = dev;
} else {
sa->ptr->next = dev;
sa->ptr = dev;
}
refcount++;
done:
return NL_SKIP;
}
static int
list_switch(struct nl_msg *msg, void *arg)
{
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
if (nla_parse(tb, SWITCH_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0)
goto done;
if (!tb[SWITCH_ATTR_DEV_NAME] || !tb[SWITCH_ATTR_NAME])
goto done;
printf("Found: %s - %s\n", nla_get_string(tb[SWITCH_ATTR_DEV_NAME]),
nla_get_string(tb[SWITCH_ATTR_ALIAS]));
done:
return NL_SKIP;
}
void
swlib_list(void)
{
if (swlib_priv_init() < 0)
return;
swlib_call(SWITCH_CMD_GET_SWITCH, list_switch, NULL, NULL);
swlib_priv_free();
}
void
swlib_print_portmap(struct switch_dev *dev, char *segment)
{
int i;
if (segment) {
if (!strcmp(segment, "cpu")) {
printf("%d ", dev->cpu_port);
} else if (!strcmp(segment, "disabled")) {
for (i = 0; i < dev->ports; i++)
if (!dev->maps[i].segment)
printf("%d ", i);
} else for (i = 0; i < dev->ports; i++) {
if (dev->maps[i].segment && !strcmp(dev->maps[i].segment, segment))
printf("%d ", i);
}
} else {
printf("%s - %s\n", dev->dev_name, dev->name);
for (i = 0; i < dev->ports; i++)
if (i == dev->cpu_port)
printf("port%d:\tcpu\n", i);
else if (dev->maps[i].segment)
printf("port%d:\t%s.%d\n", i, dev->maps[i].segment, dev->maps[i].virt);
else
printf("port%d:\tdisabled\n", i);
}
}
struct switch_dev *
swlib_connect(const char *name)
{
struct swlib_scan_arg arg;
if (!refcount) {
if (swlib_priv_init() < 0)
return NULL;
};
arg.head = NULL;
arg.ptr = NULL;
arg.name = name;
swlib_call(SWITCH_CMD_GET_SWITCH, add_switch, NULL, &arg);
if (!refcount)
swlib_priv_free();
return arg.head;
}
static void
swlib_free_attributes(struct switch_attr **head)
{
struct switch_attr *a = *head;
struct switch_attr *next;
while (a) {
next = a->next;
free(a->name);
free(a->description);
free(a);
a = next;
}
*head = NULL;
}
static void
swlib_free_port_map(struct switch_dev *dev)
{
int i;
if (!dev || !dev->maps)
return;
for (i = 0; i < dev->ports; i++)
free(dev->maps[i].segment);
free(dev->maps);
}
void
swlib_free(struct switch_dev *dev)
{
swlib_free_attributes(&dev->ops);
swlib_free_attributes(&dev->port_ops);
swlib_free_attributes(&dev->vlan_ops);
swlib_free_port_map(dev);
free(dev->name);
free(dev->alias);
free(dev);
if (--refcount == 0)
swlib_priv_free();
}
void
swlib_free_all(struct switch_dev *dev)
{
struct switch_dev *p;
while (dev) {
p = dev->next;
swlib_free(dev);
dev = p;
}
}

View File

@@ -0,0 +1,269 @@
/*
* swlib.h: Switch configuration API (user space part)
*
* Copyright (C) 2008-2009 Felix Fietkau <nbd@nbd.name>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* 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.
*
Usage of the library functions:
The main datastructure for a switch is the struct switch_device
To get started, you first need to use switch_connect() to probe
for switches and allocate an instance of this struct.
There are two possible usage modes:
dev = switch_connect("eth0");
- this call will look for a switch registered for the linux device
"eth0" and only allocate a switch_device for this particular switch.
dev = switch_connect(NULL)
- this will return one switch_device struct for each available
switch. The switch_device structs are chained with by ->next pointer
Then to query a switch for all available attributes, use:
swlib_scan(dev);
All allocated datastructures for the switch_device struct can be freed with
swlib_free(dev);
or
swlib_free_all(dev);
The latter traverses a whole chain of switch_device structs and frees them all
Switch attributes (struct switch_attr) are divided into three groups:
dev->ops:
- global settings
dev->port_ops:
- per-port settings
dev->vlan_ops:
- per-vlan settings
switch_lookup_attr() is a small helper function to locate attributes
by name.
switch_set_attr() and switch_get_attr() can alter or request the values
of attributes.
Usage of the switch_attr struct:
->atype: attribute group, one of:
- SWLIB_ATTR_GROUP_GLOBAL
- SWLIB_ATTR_GROUP_VLAN
- SWLIB_ATTR_GROUP_PORT
->id: identifier for the attribute
->type: data type, one of:
- SWITCH_TYPE_INT
- SWITCH_TYPE_STRING
- SWITCH_TYPE_PORT
->name: short name of the attribute
->description: longer description
->next: pointer to the next attribute of the current group
Usage of the switch_val struct:
When setting attributes, following members of the struct switch_val need
to be set up:
->len (for attr->type == SWITCH_TYPE_PORT)
->port_vlan:
- port number (for attr->atype == SWLIB_ATTR_GROUP_PORT), or:
- vlan number (for attr->atype == SWLIB_ATTR_GROUP_VLAN)
->value.i (for attr->type == SWITCH_TYPE_INT)
->value.s (for attr->type == SWITCH_TYPE_STRING)
- owned by the caller, not stored in the library internally
->value.ports (for attr->type == SWITCH_TYPE_PORT)
- must point to an array of at lest val->len * sizeof(struct switch_port)
When getting string attributes, val->value.s must be freed by the caller
When getting port list attributes, an internal static buffer is used,
which changes from call to call.
*/
#ifndef __SWLIB_H
#define __SWLIB_H
enum swlib_attr_group {
SWLIB_ATTR_GROUP_GLOBAL,
SWLIB_ATTR_GROUP_VLAN,
SWLIB_ATTR_GROUP_PORT,
};
enum swlib_port_flags {
SWLIB_PORT_FLAG_TAGGED = (1 << 0),
};
enum swlib_link_flags {
SWLIB_LINK_FLAG_EEE_100BASET = (1 << 0),
SWLIB_LINK_FLAG_EEE_1000BASET = (1 << 1),
};
struct switch_dev;
struct switch_attr;
struct switch_port;
struct switch_port_map;
struct switch_port_link;
struct switch_val;
struct uci_package;
struct switch_dev {
int id;
char dev_name[IFNAMSIZ];
char *name;
char *alias;
int ports;
int vlans;
int cpu_port;
struct switch_attr *ops;
struct switch_attr *port_ops;
struct switch_attr *vlan_ops;
struct switch_portmap *maps;
struct switch_dev *next;
void *priv;
};
struct switch_val {
struct switch_attr *attr;
int len;
int err;
int port_vlan;
union {
char *s;
int i;
struct switch_port *ports;
struct switch_port_link *link;
} value;
};
struct switch_attr {
struct switch_dev *dev;
int atype;
int id;
int type;
char *name;
char *description;
struct switch_attr *next;
};
struct switch_port {
unsigned int id;
unsigned int flags;
};
struct switch_portmap {
unsigned int virt;
char *segment;
};
struct switch_port_link {
int link:1;
int duplex:1;
int aneg:1;
int tx_flow:1;
int rx_flow:1;
int speed;
/* in ethtool adv_t format */
uint32_t eee;
};
/**
* swlib_list: list all switches
*/
void swlib_list(void);
/**
* swlib_print_portmap: get portmap
* @dev: switch device struct
*/
void swlib_print_portmap(struct switch_dev *dev, char *segment);
/**
* swlib_connect: connect to the switch through netlink
* @name: name of the ethernet interface,
*
* if name is NULL, it connect and builds a chain of all switches
*/
struct switch_dev *swlib_connect(const char *name);
/**
* swlib_free: free all dynamically allocated data for the switch connection
* @dev: switch device struct
*
* all members of a switch device chain (generated by swlib_connect(NULL))
* must be freed individually
*/
void swlib_free(struct switch_dev *dev);
/**
* swlib_free_all: run swlib_free on all devices in the chain
* @dev: switch device struct
*/
void swlib_free_all(struct switch_dev *dev);
/**
* swlib_scan: probe the switch driver for available commands/attributes
* @dev: switch device struct
*/
int swlib_scan(struct switch_dev *dev);
/**
* swlib_lookup_attr: look up a switch attribute
* @dev: switch device struct
* @type: global, port or vlan
* @name: name of the attribute
*/
struct switch_attr *swlib_lookup_attr(struct switch_dev *dev,
enum swlib_attr_group atype, const char *name);
/**
* swlib_set_attr: set the value for an attribute
* @dev: switch device struct
* @attr: switch attribute struct
* @val: attribute value pointer
* returns 0 on success
*/
int swlib_set_attr(struct switch_dev *dev, struct switch_attr *attr,
struct switch_val *val);
/**
* swlib_set_attr_string: set the value for an attribute with type conversion
* @dev: switch device struct
* @attr: switch attribute struct
* @port_vlan: port or vlan (if applicable)
* @str: string value
* returns 0 on success
*/
int swlib_set_attr_string(struct switch_dev *dev, struct switch_attr *attr,
int port_vlan, const char *str);
/**
* swlib_get_attr: get the value for an attribute
* @dev: switch device struct
* @attr: switch attribute struct
* @val: attribute value pointer
* returns 0 on success
* for string attributes, the result string must be freed by the caller
*/
int swlib_get_attr(struct switch_dev *dev, struct switch_attr *attr,
struct switch_val *val);
/**
* swlib_apply_from_uci: set up the switch from a uci configuration
* @dev: switch device struct
* @p: uci package which contains the desired global config
*/
int swlib_apply_from_uci(struct switch_dev *dev, struct uci_package *p);
#endif

View File

@@ -0,0 +1,246 @@
/*
* uci.c: UCI binding for the switch configuration utility
*
* Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundatio.
*
* 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.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <stdint.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <uci.h>
#include <linux/types.h>
#include <linux/netlink.h>
#include <linux/genetlink.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <linux/switch.h>
#include "swlib.h"
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#endif
struct swlib_setting {
struct switch_attr *attr;
const char *name;
int port_vlan;
const char *val;
struct swlib_setting *next;
};
struct swlib_setting early_settings[] = {
{ .name = "reset", .val = "1" },
{ .name = "enable_vlan", .val = "1" },
};
static struct swlib_setting *settings;
static struct swlib_setting **head;
static bool swlib_match_name(struct switch_dev *dev, const char *name)
{
return (strcmp(name, dev->dev_name) == 0 ||
strcmp(name, dev->alias) == 0);
}
static void
swlib_map_settings(struct switch_dev *dev, int type, int port_vlan, struct uci_section *s)
{
struct swlib_setting *setting;
struct switch_attr *attr;
struct uci_element *e;
struct uci_option *o;
uci_foreach_element(&s->options, e) {
o = uci_to_option(e);
if (o->type != UCI_TYPE_STRING)
continue;
if (!strcmp(e->name, "device"))
continue;
/* map early settings */
if (type == SWLIB_ATTR_GROUP_GLOBAL) {
int i;
for (i = 0; i < ARRAY_SIZE(early_settings); i++) {
if (strcmp(e->name, early_settings[i].name) != 0)
continue;
early_settings[i].val = o->v.string;
goto skip;
}
}
attr = swlib_lookup_attr(dev, type, e->name);
if (!attr)
continue;
setting = malloc(sizeof(struct swlib_setting));
memset(setting, 0, sizeof(struct swlib_setting));
setting->attr = attr;
setting->port_vlan = port_vlan;
setting->val = o->v.string;
*head = setting;
head = &setting->next;
skip:
continue;
}
}
int swlib_apply_from_uci(struct switch_dev *dev, struct uci_package *p)
{
struct switch_attr *attr;
struct uci_element *e;
struct uci_section *s;
struct uci_option *o;
struct uci_ptr ptr;
struct switch_val val;
int i;
settings = NULL;
head = &settings;
uci_foreach_element(&p->sections, e) {
struct uci_element *n;
s = uci_to_section(e);
if (strcmp(s->type, "switch") != 0)
continue;
uci_foreach_element(&s->options, n) {
struct uci_option *o = uci_to_option(n);
if (strcmp(n->name, "name") != 0)
continue;
if (o->type != UCI_TYPE_STRING)
continue;
if (swlib_match_name(dev, o->v.string))
goto found;
break;
}
if (!swlib_match_name(dev, e->name))
continue;
goto found;
}
/* not found */
return -1;
found:
/* look up available early options, which need to be taken care
* of in the correct order */
for (i = 0; i < ARRAY_SIZE(early_settings); i++) {
early_settings[i].attr = swlib_lookup_attr(dev,
SWLIB_ATTR_GROUP_GLOBAL, early_settings[i].name);
}
swlib_map_settings(dev, SWLIB_ATTR_GROUP_GLOBAL, 0, s);
/* look for port or vlan sections */
uci_foreach_element(&p->sections, e) {
struct uci_element *os;
s = uci_to_section(e);
if (!strcmp(s->type, "switch_port")) {
char *devn = NULL, *port = NULL, *port_err = NULL;
int port_n;
uci_foreach_element(&s->options, os) {
o = uci_to_option(os);
if (o->type != UCI_TYPE_STRING)
continue;
if (!strcmp(os->name, "device")) {
devn = o->v.string;
if (!swlib_match_name(dev, devn))
devn = NULL;
} else if (!strcmp(os->name, "port")) {
port = o->v.string;
}
}
if (!devn || !port || !port[0])
continue;
port_n = strtoul(port, &port_err, 0);
if (port_err && port_err[0])
continue;
swlib_map_settings(dev, SWLIB_ATTR_GROUP_PORT, port_n, s);
} else if (!strcmp(s->type, "switch_vlan")) {
char *devn = NULL, *vlan = NULL, *vlan_err = NULL;
int vlan_n;
uci_foreach_element(&s->options, os) {
o = uci_to_option(os);
if (o->type != UCI_TYPE_STRING)
continue;
if (!strcmp(os->name, "device")) {
devn = o->v.string;
if (!swlib_match_name(dev, devn))
devn = NULL;
} else if (!strcmp(os->name, "vlan")) {
vlan = o->v.string;
}
}
if (!devn || !vlan || !vlan[0])
continue;
vlan_n = strtoul(vlan, &vlan_err, 0);
if (vlan_err && vlan_err[0])
continue;
swlib_map_settings(dev, SWLIB_ATTR_GROUP_VLAN, vlan_n, s);
}
}
for (i = 0; i < ARRAY_SIZE(early_settings); i++) {
struct swlib_setting *st = &early_settings[i];
if (!st->attr || !st->val)
continue;
swlib_set_attr_string(dev, st->attr, st->port_vlan, st->val);
}
while (settings) {
struct swlib_setting *st = settings;
swlib_set_attr_string(dev, st->attr, st->port_vlan, st->val);
st = st->next;
free(settings);
settings = st;
}
/* Apply the config */
attr = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_GLOBAL, "apply");
if (!attr)
return 0;
memset(&val, 0, sizeof(val));
swlib_set_attr(dev, attr, &val);
return 0;
}

View File

@@ -0,0 +1,73 @@
#
# Copyright (C) 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:=vti
PKG_RELEASE:=4
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
define Package/vti/Default
SECTION:=net
CATEGORY:=Network
MAINTAINER:=Andre Valentin <avalentin@marcant.net>
PKGARCH:=all
endef
define Package/vti
$(call Package/vti/Default)
TITLE:=Virtual IPsec Tunnel Interface config support
endef
define Package/vti/description
Virtual IPsec Tunnel Interface config support (IPv4 and IPv6) in /etc/config/network.
endef
define Package/vtiv4
$(call Package/vti/Default)
TITLE:=Virtual IPsec Tunnel Interface (IPv4) config support
DEPENDS:=@(PACKAGE_vti) +kmod-ip-vti
endef
define Package/vtiv4/description
Virtual IPsec Tunnel Interface config support (IPv4) in /etc/config/network.
endef
define Package/vtiv6
$(call Package/vti/Default)
TITLE:=Virtual IPsec Tunnel Interface (IPv6) config support
DEPENDS:=@(PACKAGE_vti) @IPV6 +kmod-ip6-vti
endef
define Package/vtiv6/description
Virtual IPsec Tunnel Interface config support (IPv6) in /etc/config/network.
endef
define Build/Compile
endef
define Build/Configure
endef
define Package/vti/install
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/vti.sh $(1)/lib/netifd/proto/vti.sh
endef
define Package/vtiv4/install
:
endef
define Package/vtiv6/install
:
endef
$(eval $(call BuildPackage,vti))
$(eval $(call BuildPackage,vtiv4))
$(eval $(call BuildPackage,vtiv6))

View File

@@ -0,0 +1,154 @@
#!/bin/sh
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. /lib/functions/network.sh
. ../netifd-proto.sh
init_proto "$@"
}
vti_generic_setup() {
local cfg="$1"
local mode="$2"
local local="$3"
local remote="$4"
local link="$5"
local mtu zone ikey
json_get_vars mtu zone ikey okey
proto_init_update "$link" 1
proto_add_tunnel
json_add_string mode "$mode"
json_add_int mtu "${mtu:-1280}"
json_add_string local "$local"
json_add_string remote "$remote"
[ -n "$tunlink" ] && json_add_string link "$tunlink"
json_add_object 'data'
[ -n "$ikey" ] && json_add_int ikey "$ikey"
[ -n "$okey" ] && json_add_int okey "$okey"
json_close_object
proto_close_tunnel
proto_add_data
[ -n "$zone" ] && json_add_string zone "$zone"
proto_close_data
proto_send_update "$cfg"
}
vti_setup() {
local cfg="$1"
local mode="$2"
local ipaddr peeraddr
json_get_vars df ipaddr peeraddr tunlink
[ -z "$peeraddr" ] && {
proto_notify_error "$cfg" "MISSING_ADDRESS"
proto_block_restart "$cfg"
exit
}
( proto_add_host_dependency "$cfg" "$peeraddr" "$tunlink" )
[ -z "$ipaddr" ] && {
local wanif="$tunlink"
if [ -z $wanif ] && ! network_find_wan wanif; then
proto_notify_error "$cfg" "NO_WAN_LINK"
exit
fi
if ! network_get_ipaddr ipaddr "$wanif"; then
proto_notify_error "$cfg" "NO_WAN_LINK"
exit
fi
}
vti_generic_setup $cfg $mode $ipaddr $peeraddr "vti-$cfg"
}
proto_vti_setup() {
local cfg="$1"
vti_setup $cfg "vtiip"
}
vti6_setup() {
local cfg="$1"
local mode="$2"
local ip6addr peer6addr weakif
json_get_vars ip6addr peer6addr tunlink weakif
[ -z "$peer6addr" ] && {
proto_notify_error "$cfg" "MISSING_ADDRESS"
proto_block_restart "$cfg"
exit
}
( proto_add_host_dependency "$cfg" "$peer6addr" "$tunlink" )
[ -z "$ip6addr" ] && {
local wanif="$tunlink"
if [ -z $wanif ] && ! network_find_wan6 wanif; then
proto_notify_error "$cfg" "NO_WAN_LINK"
exit
fi
if ! network_get_ipaddr6 ip6addr "$wanif"; then
[ -z "$weakif" ] && weakif="lan"
if ! network_get_ipaddr6 ip6addr "$weakif"; then
proto_notify_error "$cfg" "NO_WAN_LINK"
exit
fi
fi
}
vti_generic_setup $cfg $mode $ip6addr $peer6addr "vti6-$cfg"
}
proto_vti6_setup() {
local cfg="$1"
vti6_setup $cfg "vtiip6"
}
proto_vti_teardown() {
local cfg="$1"
}
proto_vti6_teardown() {
local cfg="$1"
}
vti_generic_init_config() {
no_device=1
available=1
proto_config_add_int "mtu"
proto_config_add_string "tunlink"
proto_config_add_string "zone"
proto_config_add_int "ikey"
proto_config_add_int "okey"
}
proto_vti_init_config() {
vti_generic_init_config
proto_config_add_string "ipaddr"
proto_config_add_string "peeraddr"
}
proto_vti6_init_config() {
vti_generic_init_config
proto_config_add_string "ip6addr"
proto_config_add_string "peer6addr"
proto_config_add_string "weakif"
}
[ -n "$INCLUDE_ONLY" ] || {
[ -d /sys/module/ip_vti ] && add_protocol vti
[ -d /sys/module/ip6_vti ] && add_protocol vti6
}

View File

@@ -0,0 +1,33 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=vxlan
PKG_RELEASE:=7
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
define Package/vxlan
SECTION:=net
CATEGORY:=Network
MAINTAINER:=Matthias Schiffer <mschiffer@universe-factory.net>
TITLE:=Virtual eXtensible LAN config support
DEPENDS:=+kmod-vxlan
PKGARCH:=all
endef
define Package/vxlan/description
Virtual eXtensible LAN config support in /etc/config/network.
endef
define Build/Compile
endef
define Build/Configure
endef
define Package/vxlan/install
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/vxlan.sh $(1)/lib/netifd/proto/vxlan.sh
endef
$(eval $(call BuildPackage,vxlan))

View File

@@ -0,0 +1,195 @@
#!/bin/sh
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. /lib/functions/network.sh
. ../netifd-proto.sh
init_proto "$@"
}
proto_vxlan_setup_peer() {
type bridge &> /dev/null || {
proto_notify_error "$cfg" "MISSING_BRIDGE_COMMAND"
exit
}
local peer_config="$1"
local vxlan
local lladdr
local dst
local src_vni
local vni
local port
local via
config_get vxlan "${peer_config}" "vxlan"
config_get lladdr "${peer_config}" "lladdr"
config_get dst "${peer_config}" "dst"
config_get src_vni "${peer_config}" "src_vni"
config_get vni "${peer_config}" "vni"
config_get port "${peer_config}" "port"
config_get via "${peer_config}" "via"
[ "$cfg" = "$vxlan" ] || {
# This peer section belongs to another device
return
}
[ -n "${dst}" ] || {
proto_notify_error "$cfg" "MISSING_PEER_ADDRESS"
exit
}
bridge fdb append \
${lladdr:-00:00:00:00:00:00} \
dev ${cfg} \
dst ${dst} \
${src_vni:+src_vni $src_vni} \
${vni:+vni $vni} \
${port:+port $port} \
${via:+via $via}
}
vxlan_generic_setup() {
local cfg="$1"
local mode="$2"
local local="$3"
local remote="$4"
local link="$cfg"
local port vid ttl tos mtu macaddr zone rxcsum txcsum srcportmin srcportmax ageing maxaddress learning rsc proxy l2miss l3miss gbp
json_get_vars port vid ttl tos mtu macaddr zone rxcsum txcsum srcportmin srcportmax ageing maxaddress learning rsc proxy l2miss l3miss gbp
proto_init_update "$link" 1
proto_add_tunnel
json_add_string mode "$mode"
[ -n "$tunlink" ] && json_add_string link "$tunlink"
[ -n "$local" ] && json_add_string local "$local"
[ -n "$remote" ] && json_add_string remote "$remote"
[ -n "$ttl" ] && json_add_int ttl "$ttl"
[ -n "$tos" ] && json_add_string tos "$tos"
[ -n "$mtu" ] && json_add_int mtu "$mtu"
json_add_object 'data'
[ -n "$port" ] && json_add_int port "$port"
[ -n "$vid" ] && json_add_int id "$vid"
[ -n "$srcportmin" ] && json_add_int srcportmin "$srcportmin"
[ -n "$srcportmax" ] && json_add_int srcportmax "$srcportmax"
[ -n "$ageing" ] && json_add_int ageing "$ageing"
[ -n "$maxaddress" ] && json_add_int maxaddress "$maxaddress"
[ -n "$macaddr" ] && json_add_string macaddr "$macaddr"
[ -n "$rxcsum" ] && json_add_boolean rxcsum "$rxcsum"
[ -n "$txcsum" ] && json_add_boolean txcsum "$txcsum"
[ -n "$learning" ] && json_add_boolean learning "$learning"
[ -n "$rsc" ] && json_add_boolean rsc "$rsc"
[ -n "$proxy" ] && json_add_boolean proxy "$proxy"
[ -n "$l2miss" ] && json_add_boolean l2miss "$l2miss"
[ -n "$l3miss" ] && json_add_boolean l3miss "$l3miss"
[ -n "$gbp" ] && json_add_boolean gbp "$gbp"
json_close_object
proto_close_tunnel
proto_add_data
[ -n "$zone" ] && json_add_string zone "$zone"
proto_close_data
proto_send_update "$cfg"
config_load network
config_foreach proto_vxlan_setup_peer "vxlan_peer"
}
proto_vxlan_setup() {
local cfg="$1"
local ipaddr peeraddr
json_get_vars ipaddr peeraddr tunlink
( proto_add_host_dependency "$cfg" '' "$tunlink" )
case "$ipaddr" in
"auto"|"")
ipaddr="0.0.0.0"
;;
esac
vxlan_generic_setup "$cfg" 'vxlan' "$ipaddr" "$peeraddr"
}
proto_vxlan6_setup() {
local cfg="$1"
local ip6addr peer6addr
json_get_vars ip6addr peer6addr tunlink
( proto_add_host_dependency "$cfg" '' "$tunlink" )
case "$ip6addr" in
"auto"|"")
# ensure tunnel via ipv6
ip6addr="::"
;;
esac
vxlan_generic_setup "$cfg" 'vxlan6' "$ip6addr" "$peer6addr"
}
proto_vxlan_teardown() {
local cfg="$1"
}
proto_vxlan6_teardown() {
local cfg="$1"
}
vxlan_generic_init_config() {
no_device=1
available=1
proto_config_add_string "tunlink"
proto_config_add_string "zone"
proto_config_add_int "vid"
proto_config_add_int "port"
proto_config_add_int "ttl"
proto_config_add_int "tos"
proto_config_add_int "mtu"
proto_config_add_int "srcportmin"
proto_config_add_int "srcportmax"
proto_config_add_int "ageing"
proto_config_add_int "maxaddress"
proto_config_add_boolean "rxcsum"
proto_config_add_boolean "txcsum"
proto_config_add_boolean "learning"
proto_config_add_boolean "rsc"
proto_config_add_boolean "proxy"
proto_config_add_boolean "l2miss"
proto_config_add_boolean "l3miss"
proto_config_add_boolean "gbp"
proto_config_add_string "macaddr"
}
proto_vxlan_init_config() {
vxlan_generic_init_config
proto_config_add_string "ipaddr"
proto_config_add_string "peeraddr"
}
proto_vxlan6_init_config() {
vxlan_generic_init_config
proto_config_add_string "ip6addr"
proto_config_add_string "peer6addr"
}
[ -n "$INCLUDE_ONLY" ] || {
add_protocol vxlan
add_protocol vxlan6
}

View File

@@ -0,0 +1,38 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=xfrm
PKG_RELEASE:=4
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
define Package/xfrm/Default
SECTION:=net
CATEGORY:=Network
MAINTAINER:=Andre Valentin <avalentin@marcant.net>
PKGARCH:=all
endef
define Package/xfrm
$(call Package/xfrm/Default)
TITLE:=XFRM IPsec Tunnel Interface config support
DEPENDS:=+kmod-xfrm-interface
endef
define Package/xfrm/description
XFRM IPsec Tunnel Interface config support (IPv4 and IPv6) in /etc/config/network.
endef
define Build/Compile
endef
define Build/Configure
endef
define Package/xfrm/install
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/xfrm.sh $(1)/lib/netifd/proto/xfrm.sh
endef
$(eval $(call BuildPackage,xfrm))

View File

@@ -0,0 +1,72 @@
#!/bin/sh
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. /lib/functions/network.sh
. ../netifd-proto.sh
init_proto "$@"
}
proto_xfrm_setup() {
local cfg="$1"
local mode="xfrm"
local tunlink ifid mtu zone multicast
json_get_vars tunlink ifid mtu zone multicast
[ -z "$tunlink" ] && {
proto_notify_error "$cfg" NO_TUNLINK
proto_block_restart "$cfg"
exit
}
[ -z "$ifid" ] && {
proto_notify_error "$cfg" NO_IFID
proto_block_restart "$cfg"
exit
}
( proto_add_host_dependency "$cfg" '' "$tunlink" )
proto_init_update "$cfg" 1
proto_add_tunnel
json_add_string mode "$mode"
json_add_int mtu "${mtu:-1280}"
json_add_string link "$tunlink"
json_add_boolean multicast "${multicast:-1}"
json_add_object 'data'
[ -n "$ifid" ] && json_add_int ifid "$ifid"
json_close_object
proto_close_tunnel
proto_add_data
[ -n "$zone" ] && json_add_string zone "$zone"
proto_close_data
proto_send_update "$cfg"
}
proto_xfrm_teardown() {
local cfg="$1"
}
proto_xfrm_init_config() {
no_device=1
available=1
proto_config_add_int "mtu"
proto_config_add_string "tunlink"
proto_config_add_string "zone"
proto_config_add_int "ifid"
proto_config_add_boolean "multicast"
}
[ -n "$INCLUDE_ONLY" ] || {
[ -d /sys/module/xfrm_interface ] && add_protocol xfrm
}

View File

@@ -0,0 +1,43 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=464xlat
PKG_RELEASE:=12
PKG_SOURCE_DATE:=2018-01-16
PKG_MAINTAINER:=Hans Dedecker <dedeckeh@gmail.com>
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
define Package/464xlat
SECTION:=net
CATEGORY:=Network
DEPENDS:=@IPV6 +kmod-nat46 +ip
TITLE:=464xlat CLAT support
endef
define Build/Prepare
$(call Build/Prepare/Default)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
CC="$(TARGET_CC)" \
CFLAGS="$(TARGET_CFLAGS) -Wall" \
LDFLAGS="$(TARGET_LDFLAGS)"
endef
define Package/464xlat/description
464xlat provides support to deploy limited IPv4 access services to mobile
and wireline IPv6-only edge networks without encapsulation (RFC6877)
endef
define Package/464xlat/install
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/464xlat.sh $(1)/lib/netifd/proto/464xlat.sh
$(INSTALL_DIR) $(1)/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/464xlatcfg $(1)/sbin
endef
$(eval $(call BuildPackage,464xlat))

View File

@@ -0,0 +1,115 @@
#!/bin/sh
# 464xlat.sh - 464xlat CLAT
#
# Copyright (c) 2015 Steven Barth <cyrus@openwrt.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2
# as published by the Free Software Foundation
#
# 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.
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. /lib/functions/network.sh
. ../netifd-proto.sh
init_proto "$@"
}
proto_464xlat_setup() {
local cfg="$1"
local iface="$2"
local link="464-$cfg"
local ip6addr ip6prefix tunlink zone
json_get_vars ip6addr ip6prefix tunlink zone
[ "$zone" = "-" ] && zone=""
( proto_add_host_dependency "$cfg" "::" "$tunlink" )
if [ -z "$tunlink" ] && ! network_find_wan6 tunlink; then
proto_notify_error "$cfg" "NO_WAN_LINK"
return
fi
network_get_device tundev "$tunlink"
ip6addr=$(464xlatcfg "$link" "$tundev" "$ip6prefix" 192.0.0.1 $ip6addr)
if [ -z "$ip6addr" ]; then
proto_notify_error "$cfg" "CLAT_CONFIG_FAILED"
return
fi
ip -6 rule del from all lookup local
ip -6 rule add from all lookup local pref 1
ip -6 rule add to $ip6addr lookup prelocal pref 0
echo "$ip6addr" > /tmp/464-$cfg-anycast
proto_init_update "$link" 1
proto_add_ipv4_route "0.0.0.0" 0 "" "" 2048
proto_add_ipv6_route $ip6addr 128 "" "" "" "" 128
proto_add_data
[ -n "$zone" ] && json_add_string zone "$zone"
json_add_array firewall
[ -z "$zone" ] && zone=$(fw3 -q network $iface 2>/dev/null)
json_add_object ""
json_add_string type nat
json_add_string target SNAT
json_add_string family inet
json_add_string snat_ip 192.0.0.1
json_close_object
[ -n "$zone" ] && {
json_add_object ""
json_add_string type rule
json_add_string family inet6
json_add_string proto all
json_add_string direction in
json_add_string dest "$zone"
json_add_string src "$zone"
json_add_string src_ip $ip6addr
json_add_string target ACCEPT
json_close_object
}
json_close_array
proto_close_data
proto_send_update "$cfg"
}
proto_464xlat_teardown() {
local cfg="$1"
local link="464-$cfg"
[ -f /tmp/464-$cfg-anycast ] || return
local ip6addr=$(cat /tmp/464-$cfg-anycast)
464xlatcfg "$link"
rm -rf /tmp/464-$cfg-anycast
[ -n "$ip6addr" ] && ip -6 rule del to $ip6addr lookup prelocal
if [ -z "$(ls /tmp/464-*-anycast 2>&-)" ]; then
ip -6 rule del from all lookup local
ip -6 rule add from all lookup local pref 0
fi
}
proto_464xlat_init_config() {
no_device=1
available=1
proto_config_add_string "ip6prefix"
proto_config_add_string "ip6addr"
proto_config_add_string "tunlink"
proto_config_add_string "zone"
}
[ -n "$INCLUDE_ONLY" ] || {
add_protocol 464xlat
}

View File

@@ -0,0 +1,154 @@
/* 464xlatcfg.c
*
* Copyright (c) 2015 Steven Barth <cyrus@openwrt.org>
* Copyright (c) 2017 Hans Dedecker <dedeckeh@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation
*
* 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.
*/
#include <netinet/icmp6.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <netdb.h>
static void sighandler(__attribute__((unused)) int signal)
{
}
int main(int argc, const char *argv[])
{
char buf[INET6_ADDRSTRLEN], prefix[INET6_ADDRSTRLEN + 4];
int pid;
if (argc <= 1) {
fprintf(stderr, "Usage: %s <name> [ifname] [ipv6prefix] [ipv4addr] [ipv6addr]\n", argv[0]);
return 1;
}
snprintf(buf, sizeof(buf), "/var/run/%s.pid", argv[1]);
FILE *fp = fopen(buf, "r");
if (fp) {
if (fscanf(fp, "%d", &pid) == 1)
kill(pid, SIGTERM);
unlink(buf);
fclose(fp);
}
if (!argv[2])
return 0;
if (!argv[3] || !argv[4] || !(fp = fopen(buf, "wx")))
return 1;
signal(SIGTERM, SIG_DFL);
setvbuf(fp, NULL, _IOLBF, 0);
fprintf(fp, "%d\n", getpid());
prefix[sizeof(prefix) - 1] = 0;
strncpy(prefix, argv[3], sizeof(prefix) - 1);
if (!prefix[0]) {
struct addrinfo hints = { .ai_family = AF_INET6 }, *res;
if (getaddrinfo("ipv4only.arpa", NULL, &hints, &res) || !res) {
sleep(3);
if (getaddrinfo("ipv4only.arpa", NULL, &hints, &res) || !res)
return 2;
}
struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)res->ai_addr;
inet_ntop(AF_INET6, &sin6->sin6_addr, prefix, sizeof(prefix) - 4);
strcat(prefix, "/96");
freeaddrinfo(res);
}
int i = 0;
int sock;
struct sockaddr_in6 saddr;
do {
socklen_t saddrlen = sizeof(saddr);
struct icmp6_filter filt;
sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
ICMP6_FILTER_SETBLOCKALL(&filt);
setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, sizeof(filt));
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, argv[2], strlen(argv[2]));
memset(&saddr, 0, sizeof(saddr));
saddr.sin6_family = AF_INET6;
saddr.sin6_addr.s6_addr32[0] = htonl(0x2001);
saddr.sin6_addr.s6_addr32[1] = htonl(0xdb8);
if (connect(sock, (struct sockaddr*)&saddr, sizeof(saddr)) ||
getsockname(sock, (struct sockaddr*)&saddr, &saddrlen))
return 3;
if (!IN6_IS_ADDR_LINKLOCAL(&saddr.sin6_addr) || argv[5])
break;
close(sock);
sleep(3);
i++;
} while (i < 3);
struct ipv6_mreq mreq = {saddr.sin6_addr, if_nametoindex(argv[2])};
if (!argv[5]) {
if (IN6_IS_ADDR_LINKLOCAL(&mreq.ipv6mr_multiaddr))
return 5;
srandom(mreq.ipv6mr_multiaddr.s6_addr32[0] ^ mreq.ipv6mr_multiaddr.s6_addr32[1] ^
mreq.ipv6mr_multiaddr.s6_addr32[2] ^ mreq.ipv6mr_multiaddr.s6_addr32[3]);
mreq.ipv6mr_multiaddr.s6_addr32[2] = random();
mreq.ipv6mr_multiaddr.s6_addr32[3] = random();
} else if (inet_pton(AF_INET6, argv[5], &mreq.ipv6mr_multiaddr) != 1) {
return 1;
}
if (setsockopt(sock, SOL_IPV6, IPV6_JOIN_ANYCAST, &mreq, sizeof(mreq)))
return 3;
inet_ntop(AF_INET6, &mreq.ipv6mr_multiaddr, buf, sizeof(buf));
fputs(buf, stdout);
fputc('\n', stdout);
fflush(stdout);
FILE *nat46 = fopen("/proc/net/nat46/control", "w");
if (!nat46 || fprintf(nat46, "add %s\nconfig %s local.style NONE local.v4 %s/32 local.v6 %s/128 "
"remote.style RFC6052 remote.v6 %s\n", argv[1], argv[1], argv[4], buf, prefix) < 0 ||
fclose(nat46))
return 4;
if (!(pid = fork())) {
fclose(fp);
fclose(stdin);
fclose(stdout);
fclose(stderr);
chdir("/");
setsid();
signal(SIGTERM, sighandler);
pause();
nat46 = fopen("/proc/net/nat46/control", "w");
if (nat46) {
fprintf(nat46, "del %s\n", argv[1]);
fclose(nat46);
}
} else {
rewind(fp);
fprintf(fp, "%d\n", pid);
}
return 0;
}

View File

@@ -0,0 +1,8 @@
all: 464xlatcfg
464xlatcfg: 464xlatcfg.c
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
clean:
rm -f 464xlatcfg

View File

@@ -0,0 +1,42 @@
#
# Copyright (C) 2010-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:=6in4
PKG_RELEASE:=27
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
define Package/6in4
SECTION:=net
CATEGORY:=Network
DEPENDS:=@IPV6 +kmod-sit +uclient-fetch
TITLE:=IPv6-in-IPv4 configuration support
MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
PKGARCH:=all
endef
define Package/6in4/description
Provides support for 6in4 tunnels in /etc/config/network.
Refer to http://wiki.openwrt.org/doc/uci/network for
configuration details.
endef
define Build/Compile
endef
define Build/Configure
endef
define Package/6in4/install
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/6in4.sh $(1)/lib/netifd/proto/6in4.sh
endef
$(eval $(call BuildPackage,6in4))

View File

@@ -0,0 +1,165 @@
#!/bin/sh
# 6in4.sh - IPv6-in-IPv4 tunnel backend
# Copyright (c) 2010-2015 OpenWrt.org
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. /lib/functions/network.sh
. ../netifd-proto.sh
init_proto "$@"
}
# Function taken from 6to4 package (6to4.sh), flipped returns
test_6in4_rfc1918()
{
local oIFS="$IFS"; IFS="."; set -- $1; IFS="$oIFS"
[ $1 -eq 10 ] && return 1
[ $1 -eq 192 ] && [ $2 -eq 168 ] && return 1
[ $1 -eq 172 ] && [ $2 -ge 16 ] && [ $2 -le 31 ] && return 1
# RFC 6598
[ $1 -eq 100 ] && [ $2 -ge 64 ] && [ $2 -le 127 ] && return 1
return 0
}
proto_6in4_update() {
sh -c '
timeout=5
(while [ $((timeout--)) -gt 0 ]; do
sleep 1
kill -0 $$ || exit 0
done; kill -9 $$) 2>/dev/null &
exec "$@"
' "$1" "$@"
}
proto_6in4_add_prefix() {
append "$3" "$1"
}
proto_6in4_setup() {
local cfg="$1"
local iface="$2"
local link="6in4-$cfg"
local mtu ttl tos ipaddr peeraddr ip6addr ip6prefix ip6prefixes tunlink tunnelid username password updatekey
json_get_vars mtu ttl tos ipaddr peeraddr ip6addr tunlink tunnelid username password updatekey
json_for_each_item proto_6in4_add_prefix ip6prefix ip6prefixes
[ -z "$peeraddr" ] && {
proto_notify_error "$cfg" "MISSING_ADDRESS"
proto_block_restart "$cfg"
return
}
( proto_add_host_dependency "$cfg" "$peeraddr" "$tunlink" )
[ -z "$ipaddr" ] && {
local wanif="$tunlink"
if [ -z "$wanif" ] && ! network_find_wan wanif; then
proto_notify_error "$cfg" "NO_WAN_LINK"
return
fi
if ! network_get_ipaddr ipaddr "$wanif"; then
proto_notify_error "$cfg" "NO_WAN_LINK"
return
fi
}
proto_init_update "$link" 1
[ -n "$ip6addr" ] && {
local local6="${ip6addr%%/*}"
local mask6="${ip6addr##*/}"
[ "$local6" = "$mask6" ] && mask6=
proto_add_ipv6_address "$local6" "$mask6"
proto_add_ipv6_route "::" 0 "" "" "" "$local6/$mask6"
}
for ip6prefix in $ip6prefixes; do
proto_add_ipv6_prefix "$ip6prefix"
proto_add_ipv6_route "::" 0 "" "" "" "$ip6prefix"
done
proto_add_tunnel
json_add_string mode sit
json_add_int mtu "${mtu:-1280}"
json_add_int ttl "${ttl:-64}"
[ -n "$tos" ] && json_add_string tos "$tos"
json_add_string local "$ipaddr"
json_add_string remote "$peeraddr"
[ -n "$tunlink" ] && json_add_string link "$tunlink"
proto_close_tunnel
proto_send_update "$cfg"
[ -n "$tunnelid" -a -n "$username" -a \( -n "$password" -o -n "$updatekey" \) ] && {
[ -n "$updatekey" ] && password="$updatekey"
local http="http"
local urlget="uclient-fetch"
local urlget_opts="-qO-"
local ca_path="${SSL_CERT_DIR:-/etc/ssl/certs}"
[ -f /lib/libustream-ssl.so ] && http=https
[ "$http" = "https" -a -z "$(find $ca_path -name "*.0" 2>/dev/null)" ] && {
urlget_opts="$urlget_opts --no-check-certificate"
}
local url="$http://ipv4.tunnelbroker.net/nic/update?hostname=$tunnelid"
test_6in4_rfc1918 "$ipaddr" && {
local url="${url}&myip=${ipaddr}"
}
local try=0
local max=3
(
set -o pipefail
while [ $((++try)) -le $max ]; do
if proto_6in4_update $urlget $urlget_opts --user="$username" --password="$password" "$url" 2>&1 | \
sed -e 's,^Killed$,timeout,' -e "s,^,update $try/$max: ," | \
logger -t "$link";
then
logger -t "$link" "updated"
return 0
fi
sleep 5
done
logger -t "$link" "update failed"
)
}
}
proto_6in4_teardown() {
local cfg="$1"
local link="6in4-$cfg"
ip link del $link
}
proto_6in4_init_config() {
no_device=1
available=1
proto_config_add_string "ipaddr"
proto_config_add_string "ip6addr"
proto_config_add_array "ip6prefix"
proto_config_add_string "peeraddr"
proto_config_add_string "tunlink"
proto_config_add_string "tunnelid"
proto_config_add_string "username"
proto_config_add_string "password"
proto_config_add_string "updatekey"
proto_config_add_int "mtu"
proto_config_add_int "ttl"
proto_config_add_string "tos"
}
[ -n "$INCLUDE_ONLY" ] || {
add_protocol 6in4
}

View File

@@ -0,0 +1,48 @@
#
# Copyright (C) 2010-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:=6rd
PKG_RELEASE:=11
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
define Package/6rd
SECTION:=net
CATEGORY:=Network
DEPENDS:=@IPV6 +kmod-sit
TITLE:=6rd configuration support
MAINTAINER:=Steven Barth <cyrus@openwrt.org>
PKGARCH:=all
endef
define Package/6rd/description
Provides support for 6rd tunnels in /etc/config/network.
Refer to http://wiki.openwrt.org/doc/uci/network for
configuration details.
endef
define Build/Configure
endef
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
CC="$(TARGET_CC)" \
CFLAGS="$(TARGET_CFLAGS) -Wall" \
LDFLAGS="$(TARGET_LDFLAGS)"
endef
define Package/6rd/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/6rdcalc $(1)/usr/sbin/
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/6rd.sh $(1)/lib/netifd/proto/6rd.sh
endef
$(eval $(call BuildPackage,6rd))

View File

@@ -0,0 +1,108 @@
#!/bin/sh
# 6rd.sh - IPv6-in-IPv4 tunnel backend
# Copyright (c) 2010-2012 OpenWrt.org
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. /lib/functions/network.sh
. ../netifd-proto.sh
init_proto "$@"
}
proto_6rd_setup() {
local cfg="$1"
local iface="$2"
local link="6rd-$cfg"
local mtu df ttl tos ipaddr peeraddr ip6prefix ip6prefixlen ip4prefixlen tunlink zone
json_get_vars mtu df ttl tos ipaddr peeraddr ip6prefix ip6prefixlen ip4prefixlen tunlink zone
[ -z "$ip6prefix" -o -z "$peeraddr" ] && {
proto_notify_error "$cfg" "MISSING_ADDRESS"
proto_block_restart "$cfg"
return
}
( proto_add_host_dependency "$cfg" "$peeraddr" "$tunlink" )
[ -z "$ipaddr" ] && {
local wanif="$tunlink"
if [ -z $wanif ] && ! network_find_wan wanif; then
proto_notify_error "$cfg" "NO_WAN_LINK"
return
fi
if ! network_get_ipaddr ipaddr "$wanif"; then
proto_notify_error "$cfg" "NO_WAN_LINK"
return
fi
}
# Determine the relay prefix.
local ip4prefixlen="${ip4prefixlen:-0}"
local ip4prefix
eval "$(ipcalc.sh "$ipaddr/$ip4prefixlen")";ip4prefix=$NETWORK
# Determine our IPv6 address.
local ip6subnet=$(6rdcalc "$ip6prefix/$ip6prefixlen" "$ipaddr/$ip4prefixlen")
local ip6addr="${ip6subnet%%::*}::1"
# Determine the IPv6 prefix
local ip6lanprefix="$ip6subnet/$(($ip6prefixlen + 32 - $ip4prefixlen))"
proto_init_update "$link" 1
proto_add_ipv6_address "$ip6addr" "$ip6prefixlen"
proto_add_ipv6_prefix "$ip6lanprefix"
proto_add_ipv6_route "::" 0 "::$peeraddr" 4096 "" "$ip6addr/$ip6prefixlen"
proto_add_ipv6_route "::" 0 "::$peeraddr" 4096 "" "$ip6lanprefix"
proto_add_tunnel
json_add_string mode sit
json_add_int mtu "${mtu:-1280}"
json_add_boolean df "${df:-1}"
json_add_int ttl "${ttl:-64}"
[ -n "$tos" ] && json_add_string tos "$tos"
json_add_string local "$ipaddr"
[ -n "$tunlink" ] && json_add_string link "$tunlink"
json_add_object 'data'
json_add_string prefix "$ip6prefix/$ip6prefixlen"
json_add_string relay-prefix "$ip4prefix/$ip4prefixlen"
json_close_object
proto_close_tunnel
proto_add_data
[ -n "$zone" ] && json_add_string zone "$zone"
proto_close_data
proto_send_update "$cfg"
}
proto_6rd_teardown() {
local cfg="$1"
local link="6rd-$cfg"
ip link del $link
}
proto_6rd_init_config() {
no_device=1
available=1
proto_config_add_int "mtu"
proto_config_add_boolean "df"
proto_config_add_int "ttl"
proto_config_add_string "tos"
proto_config_add_string "ipaddr"
proto_config_add_string "peeraddr"
proto_config_add_string "ip6prefix"
proto_config_add_string "ip6prefixlen"
proto_config_add_string "ip4prefixlen"
proto_config_add_string "tunlink"
proto_config_add_string "zone"
}
[ -n "$INCLUDE_ONLY" ] || {
add_protocol 6rd
}

View File

@@ -0,0 +1,126 @@
/*
* Utility used to calculate the 6rd subnet.
*
* Copyright 2012, Stéphan Kochen <stephan@kochen.nl>
*
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/errno.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define INET_PREFIXSTRLEN (INET_ADDRSTRLEN+3)
#define INET6_PREFIXSTRLEN (INET6_ADDRSTRLEN+4)
static void print_usage()
{
fprintf(stderr, "Usage: 6rdcalc <v6 prefix>/<mask> <v4 address>/<mask>\n");
exit(1);
}
static void print_error()
{
fprintf(stderr, "%s", strerror(errno));
exit(1);
}
static void parse_str(int af, char *str, void *addr, unsigned long *mask)
{
int ret;
char *slash;
/* Split the address at the slash. */
if ((slash = strchr(str, '/')) == NULL)
print_usage();
*slash = '\0';
/* Parse the address. */
if ((ret = inet_pton(af, str, addr)) != 1) {
if (ret == 0)
print_usage();
else
print_error();
}
/* Parse the mask. */
*mask = strtoul(slash+1, NULL, 10);
if ((af == AF_INET && *mask > 32) ||
(af == AF_INET6 && *mask > 128))
print_usage();
}
int main(int argc, const char **argv)
{
char v6str[INET6_PREFIXSTRLEN], v4str[INET_PREFIXSTRLEN];
struct in6_addr v6;
struct in_addr v4;
unsigned long v6it, v4it, mask;
unsigned char *byte4, *byte6;
unsigned char bit4, bit6;
/* Check parameters. */
if (argc != 3)
print_usage();
/* Parse the v6 address. */
strncpy(v6str, argv[1], INET6_PREFIXSTRLEN);
v6str[INET6_PREFIXSTRLEN-1] = '\0';
parse_str(AF_INET6, v6str, &v6, &v6it);
/* Parse the v4 address */
strncpy(v4str, argv[2], INET_PREFIXSTRLEN);
v6str[INET_PREFIXSTRLEN-1] = '\0';
parse_str(AF_INET, v4str, &v4, &v4it);
/* Check if the combined mask is within bounds. */
mask = (32 - v4it) + v6it;
if (mask > 128)
print_usage();
/* Combine the addresses. */
while (v4it < 32) {
byte6 = (unsigned char *)(&v6.s6_addr) + (v6it >> 3);
byte4 = (unsigned char *)(&v4.s_addr) + (v4it >> 3);
bit6 = 128 >> (v6it & 0x07);
bit4 = 128 >> (v4it & 0x07);
if (*byte4 & bit4)
*byte6 |= bit6;
else
*byte6 &= ~bit6;
v4it++; v6it++;
}
/* Clear remaining bits. */
while (v6it < 128) {
byte6 = (unsigned char *)(&v6.s6_addr) + (v6it >> 3);
bit6 = 128 >> (v6it & 0x07);
*byte6 &= ~bit6;
v6it++;
}
/* Print the subnet prefix. */
if (inet_ntop(AF_INET6, &v6, v6str, sizeof(v6str)) == NULL)
print_error();
printf("%s/%lu\n", v6str, mask);
return 0;
}

View File

@@ -0,0 +1,7 @@
all: 6rdcalc
6rdcalc: 6rdcalc.c
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
clean:
rm -f 6rdcalc

View File

@@ -0,0 +1,42 @@
#
# Copyright (C) 2010-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:=6to4
PKG_RELEASE:=13
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
define Package/6to4
SECTION:=net
CATEGORY:=Network
DEPENDS:=@IPV6 +kmod-sit
TITLE:=IPv6-to-IPv4 configuration support
MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
PKGARCH:=all
endef
define Package/6to4/description
Provides support for 6to4 tunnels in /etc/config/network.
Refer to https://openwrt.org/docs/guide-user/base-system/basic-networking
configuration details.
endef
define Build/Compile
endef
define Build/Configure
endef
define Package/6to4/install
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/6to4.sh $(1)/lib/netifd/proto/6to4.sh
endef
$(eval $(call BuildPackage,6to4))

View File

@@ -0,0 +1,98 @@
#!/bin/sh
# 6to4.sh - IPv6-in-IPv4 tunnel backend
# Copyright (c) 2010-2012 OpenWrt.org
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. /lib/functions/network.sh
. ../netifd-proto.sh
init_proto "$@"
}
find_6to4_prefix() {
local ip4="$1"
local oIFS="$IFS"; IFS="."; set -- $ip4; IFS="$oIFS"
printf "2002:%02x%02x:%02x%02x\n" $1 $2 $3 $4
}
test_6to4_rfc1918()
{
local oIFS="$IFS"; IFS="."; set -- $1; IFS="$oIFS"
[ $1 -eq 10 ] && return 0
[ $1 -eq 192 ] && [ $2 -eq 168 ] && return 0
[ $1 -eq 172 ] && [ $2 -ge 16 ] && [ $2 -le 31 ] && return 0
# RFC 6598
[ $1 -eq 100 ] && [ $2 -ge 64 ] && [ $2 -le 127 ] && return 0
return 1
}
proto_6to4_setup() {
local cfg="$1"
local iface="$2"
local link="6to4-$cfg"
local mtu ttl tos ipaddr
json_get_vars mtu ttl tos ipaddr
( proto_add_host_dependency "$cfg" 0.0.0.0 )
local wanif
if ! network_find_wan wanif; then
proto_notify_error "$cfg" "NO_WAN_LINK"
return
fi
[ -z "$ipaddr" ] && {
if ! network_get_ipaddr ipaddr "$wanif"; then
proto_notify_error "$cfg" "NO_WAN_ADDRESS"
return
fi
}
test_6to4_rfc1918 "$ipaddr" && {
proto_notify_error "$cfg" "INVALID_LOCAL_ADDRESS"
return
}
# find our local prefix
local prefix6=$(find_6to4_prefix "$ipaddr")
local local6="$prefix6::1"
proto_init_update "$link" 1
proto_add_ipv6_address "$local6" 16
proto_add_ipv6_prefix "$prefix6::/48"
proto_add_ipv6_route "::" 0 "::192.88.99.1" "" "" "$local6/16"
proto_add_ipv6_route "::" 0 "::192.88.99.1" "" "" "$prefix6::/48"
proto_add_tunnel
json_add_string mode sit
json_add_int mtu "${mtu:-1280}"
json_add_int ttl "${ttl:-64}"
[ -n "$tos" ] && json_add_string tos "$tos"
json_add_string local "$ipaddr"
proto_close_tunnel
proto_send_update "$cfg"
}
proto_6to4_teardown() {
local cfg="$1"
}
proto_6to4_init_config() {
no_device=1
available=1
proto_config_add_string "ipaddr"
proto_config_add_int "mtu"
proto_config_add_int "ttl"
proto_config_add_string "tos"
}
[ -n "$INCLUDE_ONLY" ] || {
add_protocol 6to4
}

View File

@@ -0,0 +1,42 @@
#
# Copyright (C) 2013 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:=ds-lite
PKG_RELEASE:=8
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
define Package/ds-lite
SECTION:=net
CATEGORY:=Network
DEPENDS:=@IPV6 +kmod-ip6-tunnel +resolveip
TITLE:=Dual-Stack Lite (DS-Lite) configuration support
MAINTAINER:=Steven Barth <steven@midlink.org>
PKGARCH:=all
endef
define Package/ds-lite/description
Provides support for Dual-Stack Lite in /etc/config/network.
Refer to http://wiki.openwrt.org/doc/uci/network for
configuration details.
endef
define Build/Compile
endef
define Build/Configure
endef
define Package/ds-lite/install
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/dslite.sh $(1)/lib/netifd/proto/dslite.sh
endef
$(eval $(call BuildPackage,ds-lite))

View File

@@ -0,0 +1,110 @@
#!/bin/sh
# dslite.sh - IPv4-in-IPv6 tunnel backend
# Copyright (c) 2013 OpenWrt.org
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. /lib/functions/network.sh
. ../netifd-proto.sh
init_proto "$@"
}
proto_dslite_setup() {
local cfg="$1"
local iface="$2"
local link="ds-$cfg"
local remoteip6
local mtu ttl peeraddr ip6addr tunlink zone weakif encaplimit
json_get_vars mtu ttl peeraddr ip6addr tunlink zone weakif encaplimit
[ -z "$peeraddr" ] && {
proto_notify_error "$cfg" "MISSING_ADDRESS"
proto_block_restart "$cfg"
return
}
( proto_add_host_dependency "$cfg" "::" "$tunlink" )
remoteip6=$(resolveip -6 "$peeraddr")
if [ -z "$remoteip6" ]; then
sleep 3
remoteip6=$(resolveip -6 "$peeraddr")
if [ -z "$remoteip6" ]; then
proto_notify_error "$cfg" "AFTR_DNS_FAIL"
return
fi
fi
for ip6 in $remoteip6; do
peeraddr=$ip6
break
done
[ -z "$ip6addr" ] && {
local wanif="$tunlink"
if [ -z "$wanif" ] && ! network_find_wan6 wanif; then
proto_notify_error "$cfg" "NO_WAN_LINK"
return
fi
if ! network_get_ipaddr6 ip6addr "$wanif"; then
[ -z "$weakif" ] && weakif="lan"
if ! network_get_ipaddr6 ip6addr "$weakif"; then
proto_notify_error "$cfg" "NO_WAN_LINK"
return
fi
fi
}
proto_init_update "$link" 1
proto_add_ipv4_route "0.0.0.0" 0
proto_add_ipv4_address "192.0.0.2" "" "" "192.0.0.1"
proto_add_tunnel
json_add_string mode ipip6
json_add_int mtu "${mtu:-1280}"
json_add_int ttl "${ttl:-64}"
json_add_string local "$ip6addr"
json_add_string remote "$peeraddr"
[ -n "$tunlink" ] && json_add_string link "$tunlink"
json_add_object "data"
[ -n "$encaplimit" ] && json_add_string encaplimit "$encaplimit"
json_close_object
proto_close_tunnel
proto_add_data
[ -n "$zone" ] && json_add_string zone "$zone"
json_add_array firewall
json_add_object ""
json_add_string type nat
json_add_string target ACCEPT
json_close_object
json_close_array
proto_close_data
proto_send_update "$cfg"
}
proto_dslite_teardown() {
local cfg="$1"
}
proto_dslite_init_config() {
no_device=1
available=1
proto_config_add_string "ip6addr"
proto_config_add_string "peeraddr"
proto_config_add_string "tunlink"
proto_config_add_int "mtu"
proto_config_add_int "ttl"
proto_config_add_string "encaplimit"
proto_config_add_string "zone"
proto_config_add_string "weakif"
}
[ -n "$INCLUDE_ONLY" ] || {
add_protocol dslite
}

View File

@@ -0,0 +1,40 @@
#
# Copyright (C) 2014-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:=map
PKG_RELEASE:=7
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/map
SECTION:=net
CATEGORY:=Network
DEPENDS:=@IPV6 +kmod-ip6-tunnel +libubox +libubus +iptables-mod-conntrack-extra +kmod-nat46
TITLE:=MAP-E/MAP-T and Lightweight 4over6 configuration support
MAINTAINER:=Hans Dedecker <dedeckeh@gmail.com>
PROVIDES:=map-t
endef
define Package/map/description
Provides support for MAP-E (RFC7597), MAP-T (RFC7599) and
Lightweight 4over6 (RFC7596) in /etc/config/network.
MAP combines address and port translation with the tunneling
of IPv4 packets over an IPv6 network
endef
define Package/map/install
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/map.sh $(1)/lib/netifd/proto/map.sh
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/mapcalc $(1)/usr/sbin/
endef
$(eval $(call BuildPackage,map))

View File

@@ -0,0 +1,245 @@
#!/bin/sh
# map.sh - IPv4-in-IPv6 tunnel backend
#
# Author: Steven Barth <cyrus@openwrt.org>
# Copyright (c) 2014 cisco Systems, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2
# as published by the Free Software Foundation
#
# 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.
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. /lib/functions/network.sh
. ../netifd-proto.sh
init_proto "$@"
}
proto_map_setup() {
local cfg="$1"
local iface="$2"
local link="map-$cfg"
local maptype type legacymap mtu ttl tunlink zone encaplimit
local rule ipaddr ip4prefixlen ip6prefix ip6prefixlen peeraddr ealen psidlen psid offset
json_get_vars maptype type legacymap mtu ttl tunlink zone encaplimit
json_get_vars rule ipaddr ip4prefixlen ip6prefix ip6prefixlen peeraddr ealen psidlen psid offset
[ "$zone" = "-" ] && zone=""
# Compatibility with older config: use $type if $maptype is missing
[ -z "$maptype" ] && maptype="$type"
[ -z "$maptype" ] && maptype="map-e"
[ -z "$ip4prefixlen" ] && ip4prefixlen=32
( proto_add_host_dependency "$cfg" "::" "$tunlink" )
# fixme: handle RA/DHCPv6 address race for LW
[ "$maptype" = lw4o6 ] && sleep 5
if [ -z "$rule" ]; then
rule="type=$maptype,ipv6prefix=$ip6prefix,prefix6len=$ip6prefixlen,ipv4prefix=$ipaddr,prefix4len=$ip4prefixlen"
[ -n "$psid" ] && rule="$rule,psid=$psid"
[ -n "$psidlen" ] && rule="$rule,psidlen=$psidlen"
[ -n "$offset" ] && rule="$rule,offset=$offset"
[ -n "$ealen" ] && rule="$rule,ealen=$ealen"
if [ "$maptype" = "map-t" ]; then
rule="$rule,dmr=$peeraddr"
else
rule="$rule,br=$peeraddr"
fi
fi
echo "rule=$rule" > /tmp/map-$cfg.rules
RULE_DATA=$(LEGACY="$legacymap" mapcalc ${tunlink:-\*} $rule)
if [ "$?" != 0 ]; then
proto_notify_error "$cfg" "INVALID_MAP_RULE"
proto_block_restart "$cfg"
return
fi
echo "$RULE_DATA" >> /tmp/map-$cfg.rules
eval $RULE_DATA
if [ -z "$RULE_BMR" ]; then
proto_notify_error "$cfg" "NO_MATCHING_PD"
proto_block_restart "$cfg"
return
fi
k=$RULE_BMR
if [ "$maptype" = "lw4o6" -o "$maptype" = "map-e" ]; then
proto_init_update "$link" 1
proto_add_ipv4_address $(eval "echo \$RULE_${k}_IPV4ADDR") "" "" ""
proto_add_tunnel
json_add_string mode ipip6
json_add_int mtu "${mtu:-1280}"
json_add_int ttl "${ttl:-64}"
json_add_string local $(eval "echo \$RULE_${k}_IPV6ADDR")
json_add_string remote $(eval "echo \$RULE_${k}_BR")
json_add_string link $(eval "echo \$RULE_${k}_PD6IFACE")
json_add_object "data"
[ -n "$encaplimit" ] && json_add_string encaplimit "$encaplimit"
if [ "$maptype" = "map-e" ]; then
json_add_array "fmrs"
for i in $(seq $RULE_COUNT); do
[ "$(eval "echo \$RULE_${i}_FMR")" != 1 ] && continue
json_add_object ""
json_add_string prefix6 "$(eval "echo \$RULE_${i}_IPV6PREFIX")/$(eval "echo \$RULE_${i}_PREFIX6LEN")"
json_add_string prefix4 "$(eval "echo \$RULE_${i}_IPV4PREFIX")/$(eval "echo \$RULE_${i}_PREFIX4LEN")"
json_add_int ealen $(eval "echo \$RULE_${i}_EALEN")
json_add_int offset $(eval "echo \$RULE_${i}_OFFSET")
json_close_object
done
json_close_array
fi
json_close_object
proto_close_tunnel
elif [ "$maptype" = "map-t" -a -f "/proc/net/nat46/control" ]; then
proto_init_update "$link" 1
local style="MAP"
[ "$legacymap" = 1 ] && style="MAP0"
echo add $link > /proc/net/nat46/control
local cfgstr="local.style $style local.v4 $(eval "echo \$RULE_${k}_IPV4PREFIX")/$(eval "echo \$RULE_${k}_PREFIX4LEN")"
cfgstr="$cfgstr local.v6 $(eval "echo \$RULE_${k}_IPV6PREFIX")/$(eval "echo \$RULE_${k}_PREFIX6LEN")"
cfgstr="$cfgstr local.ea-len $(eval "echo \$RULE_${k}_EALEN") local.psid-offset $(eval "echo \$RULE_${k}_OFFSET")"
cfgstr="$cfgstr remote.v4 0.0.0.0/0 remote.v6 $(eval "echo \$RULE_${k}_DMR") remote.style RFC6052 remote.ea-len 0 remote.psid-offset 0"
echo config $link $cfgstr > /proc/net/nat46/control
for i in $(seq $RULE_COUNT); do
[ "$(eval "echo \$RULE_${i}_FMR")" != 1 ] && continue
local cfgstr="remote.style $style remote.v4 $(eval "echo \$RULE_${i}_IPV4PREFIX")/$(eval "echo \$RULE_${i}_PREFIX4LEN")"
cfgstr="$cfgstr remote.v6 $(eval "echo \$RULE_${i}_IPV6PREFIX")/$(eval "echo \$RULE_${i}_PREFIX6LEN")"
cfgstr="$cfgstr remote.ea-len $(eval "echo \$RULE_${i}_EALEN") remote.psid-offset $(eval "echo \$RULE_${i}_OFFSET")"
echo insert $link $cfgstr > /proc/net/nat46/control
done
else
proto_notify_error "$cfg" "UNSUPPORTED_TYPE"
proto_block_restart "$cfg"
fi
proto_add_ipv4_route "0.0.0.0" 0
proto_add_data
[ -n "$zone" ] && json_add_string zone "$zone"
json_add_array firewall
if [ -z "$(eval "echo \$RULE_${k}_PORTSETS")" ]; then
json_add_object ""
json_add_string type nat
json_add_string target SNAT
json_add_string family inet
json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR")
json_close_object
else
for portset in $(eval "echo \$RULE_${k}_PORTSETS"); do
for proto in icmp tcp udp; do
json_add_object ""
json_add_string type nat
json_add_string target SNAT
json_add_string family inet
json_add_string proto "$proto"
json_add_boolean connlimit_ports 1
json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR")
json_add_string snat_port "$portset"
json_close_object
done
done
fi
if [ "$maptype" = "map-t" ]; then
[ -z "$zone" ] && zone=$(fw3 -q network $iface 2>/dev/null)
[ -n "$zone" ] && {
json_add_object ""
json_add_string type rule
json_add_string family inet6
json_add_string proto all
json_add_string direction in
json_add_string dest "$zone"
json_add_string src "$zone"
json_add_string src_ip $(eval "echo \$RULE_${k}_IPV6ADDR")
json_add_string target ACCEPT
json_close_object
json_add_object ""
json_add_string type rule
json_add_string family inet6
json_add_string proto all
json_add_string direction out
json_add_string dest "$zone"
json_add_string src "$zone"
json_add_string dest_ip $(eval "echo \$RULE_${k}_IPV6ADDR")
json_add_string target ACCEPT
json_close_object
}
proto_add_ipv6_route $(eval "echo \$RULE_${k}_IPV6ADDR") 128
fi
json_close_array
proto_close_data
proto_send_update "$cfg"
if [ "$maptype" = "lw4o6" -o "$maptype" = "map-e" ]; then
json_init
json_add_string name "${cfg}_"
json_add_string ifname "@$(eval "echo \$RULE_${k}_PD6IFACE")"
json_add_string proto "static"
json_add_array ip6addr
json_add_string "" "$(eval "echo \$RULE_${k}_IPV6ADDR")"
json_close_array
json_close_object
ubus call network add_dynamic "$(json_dump)"
fi
}
proto_map_teardown() {
local cfg="$1"
local link="map-$cfg"
json_get_var type type
[ -z "$maptype" ] && maptype="$type"
[ -z "$maptype" ] && maptype="map-e"
case "$maptype" in
"map-e"|"lw4o6") ifdown "${cfg}_" ;;
"map-t") [ -f "/proc/net/nat46/control" ] && echo del $link > /proc/net/nat46/control ;;
esac
rm -f /tmp/map-$cfg.rules
}
proto_map_init_config() {
no_device=1
available=1
proto_config_add_string "maptype"
proto_config_add_string "rule"
proto_config_add_string "ipaddr"
proto_config_add_int "ip4prefixlen"
proto_config_add_string "ip6prefix"
proto_config_add_int "ip6prefixlen"
proto_config_add_string "peeraddr"
proto_config_add_int "ealen"
proto_config_add_int "psidlen"
proto_config_add_int "psid"
proto_config_add_int "offset"
proto_config_add_boolean "legacymap"
proto_config_add_string "tunlink"
proto_config_add_int "mtu"
proto_config_add_int "ttl"
proto_config_add_string "zone"
proto_config_add_string "encaplimit"
}
[ -n "$INCLUDE_ONLY" ] || {
add_protocol map
}

View File

@@ -0,0 +1,29 @@
cmake_minimum_required(VERSION 2.8.1)
project(mapcalc C)
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -std=c99")
FIND_PATH(ubus_include_dir libubus.h)
INCLUDE_DIRECTORIES(${ubus_include_dir})
add_definitions(-D_GNU_SOURCE -Wall -Wno-gnu -Wextra)
add_executable(mapcalc mapcalc.c)
target_link_libraries(mapcalc ubus ubox)
install(TARGETS mapcalc DESTINATION sbin/)
# Packaging rules
set(CPACK_PACKAGE_VERSION "1")
set(CPACK_PACKAGE_CONTACT "Steven Barth <steven@midlink.org>")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "hnetd")
set(CPACK_GENERATOR "DEB;RPM;STGZ")
set(CPACK_STRIP_FILES true)
SET(CPACK_DEBIAN_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION})
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}_${CPACK_DEBIAN_PACKAGE_VERSION}")
include(CPack)

View File

@@ -0,0 +1,418 @@
/*
* mapcalc - MAP parameter calculation
*
* Author: Steven Barth <cyrus@openwrt.org>
* Copyright (c) 2014-2015 cisco Systems, Inc.
* Copyright (c) 2015 Steven Barth <cyrus@openwrt.org>
* Copyright (c) 2018 Hans Dedecker <dedeckeh@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation
*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <errno.h>
#include <libubus.h>
#include <libubox/utils.h>
struct blob_attr *dump = NULL;
enum {
DUMP_ATTR_INTERFACE,
DUMP_ATTR_MAX
};
static const struct blobmsg_policy dump_attrs[DUMP_ATTR_MAX] = {
[DUMP_ATTR_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_ARRAY },
};
enum {
IFACE_ATTR_INTERFACE,
IFACE_ATTR_PREFIX,
IFACE_ATTR_ADDRESS,
IFACE_ATTR_MAX,
};
static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = {
[IFACE_ATTR_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_STRING },
[IFACE_ATTR_PREFIX] = { .name = "ipv6-prefix", .type = BLOBMSG_TYPE_ARRAY },
[IFACE_ATTR_ADDRESS] = { .name = "ipv6-address", .type = BLOBMSG_TYPE_ARRAY },
};
enum {
PREFIX_ATTR_ADDRESS,
PREFIX_ATTR_MASK,
PREFIX_ATTR_MAX,
};
static const struct blobmsg_policy prefix_attrs[PREFIX_ATTR_MAX] = {
[PREFIX_ATTR_ADDRESS] = { .name = "address", .type = BLOBMSG_TYPE_STRING },
[PREFIX_ATTR_MASK] = { .name = "mask", .type = BLOBMSG_TYPE_INT32 },
};
static int bmemcmp(const void *av, const void *bv, size_t bits)
{
const uint8_t *a = av, *b = bv;
size_t bytes = bits / 8;
bits %= 8;
int res = memcmp(a, b, bytes);
if (res == 0 && bits > 0)
res = (a[bytes] >> (8 - bits)) - (b[bytes] >> (8 - bits));
return res;
}
static void bmemcpy(void *av, const void *bv, size_t bits)
{
uint8_t *a = av;
const uint8_t *b = bv;
size_t bytes = bits / 8;
bits %= 8;
memcpy(a, b, bytes);
if (bits > 0) {
uint8_t mask = (1 << (8 - bits)) - 1;
a[bytes] = (a[bytes] & mask) | ((~mask) & b[bytes]);
}
}
static void bmemcpys64(void *av, const void *bv, size_t frombits, size_t nbits)
{
uint64_t buf = 0;
const uint8_t *b = bv;
size_t frombyte = frombits / 8, tobyte = (frombits + nbits) / 8;
memcpy(&buf, &b[frombyte], tobyte - frombyte + 1);
buf = cpu_to_be64(be64_to_cpu(buf) << (frombits % 8));
bmemcpy(av, &buf, nbits);
}
static void handle_dump(struct ubus_request *req __attribute__((unused)),
int type __attribute__((unused)), struct blob_attr *msg)
{
struct blob_attr *tb[DUMP_ATTR_INTERFACE];
blobmsg_parse(dump_attrs, DUMP_ATTR_MAX, tb, blob_data(msg), blob_len(msg));
if (!tb[DUMP_ATTR_INTERFACE])
return;
dump = blob_memdup(tb[DUMP_ATTR_INTERFACE]);
}
static void match_prefix(int *pdlen, struct in6_addr *pd, struct blob_attr *cur,
const struct in6_addr *ipv6prefix, int prefix6len, bool lw4o6)
{
struct blob_attr *d;
unsigned drem;
if (!cur || blobmsg_type(cur) != BLOBMSG_TYPE_ARRAY || !blobmsg_check_attr(cur, false))
return;
blobmsg_for_each_attr(d, cur, drem) {
struct blob_attr *ptb[PREFIX_ATTR_MAX];
blobmsg_parse(prefix_attrs, PREFIX_ATTR_MAX, ptb,
blobmsg_data(d), blobmsg_data_len(d));
if (!ptb[PREFIX_ATTR_ADDRESS] || !ptb[PREFIX_ATTR_MASK])
continue;
struct in6_addr prefix = IN6ADDR_ANY_INIT;
int mask = blobmsg_get_u32(ptb[PREFIX_ATTR_MASK]);
inet_pton(AF_INET6, blobmsg_get_string(ptb[PREFIX_ATTR_ADDRESS]), &prefix);
// lw4over6 /128-address-as-PD matching madness workaround
if (lw4o6 && mask == 128)
mask = 64;
if (*pdlen < mask && mask >= prefix6len &&
!bmemcmp(&prefix, ipv6prefix, prefix6len)) {
bmemcpy(pd, &prefix, mask);
*pdlen = mask;
} else if (lw4o6 && *pdlen < prefix6len && mask < prefix6len &&
!bmemcmp(&prefix, ipv6prefix, mask)) {
bmemcpy(pd, ipv6prefix, prefix6len);
*pdlen = prefix6len;
}
}
}
enum {
OPT_TYPE,
OPT_FMR,
OPT_EALEN,
OPT_PREFIX4LEN,
OPT_PREFIX6LEN,
OPT_IPV6PREFIX,
OPT_IPV4PREFIX,
OPT_OFFSET,
OPT_PSIDLEN,
OPT_PSID,
OPT_BR,
OPT_DMR,
OPT_PD,
OPT_PDLEN,
OPT_MAX
};
static char *const token[] = {
[OPT_TYPE] = "type",
[OPT_FMR] = "fmr",
[OPT_EALEN] = "ealen",
[OPT_PREFIX4LEN] = "prefix4len",
[OPT_PREFIX6LEN] = "prefix6len",
[OPT_IPV6PREFIX] = "ipv6prefix",
[OPT_IPV4PREFIX] = "ipv4prefix",
[OPT_OFFSET] = "offset",
[OPT_PSIDLEN] = "psidlen",
[OPT_PSID] = "psid",
[OPT_BR] = "br",
[OPT_DMR] = "dmr",
[OPT_PD] = "pd",
[OPT_PDLEN] = "pdlen",
[OPT_MAX] = NULL
};
int main(int argc, char *argv[])
{
int status = 0;
const char *iface = argv[1];
const char *legacy_env = getenv("LEGACY");
bool legacy = legacy_env && atoi(legacy_env);
if (argc < 3) {
fprintf(stderr, "Usage: %s <interface|*> <rule1> [rule2] [...]\n", argv[0]);
return 1;
}
uint32_t network_interface;
struct ubus_context *ubus = ubus_connect(NULL);
if (ubus) {
ubus_lookup_id(ubus, "network.interface", &network_interface);
ubus_invoke(ubus, network_interface, "dump", NULL, handle_dump, NULL, 5000);
}
int rulecnt = 0;
for (int i = 2; i < argc; ++i) {
bool lw4o6 = false;
bool fmr = false;
int ealen = -1;
int addr4len = 32;
int prefix4len = 32;
int prefix6len = -1;
int pdlen = -1;
struct in_addr ipv4prefix = {INADDR_ANY};
struct in_addr ipv4addr = {INADDR_ANY};
struct in6_addr ipv6addr = IN6ADDR_ANY_INIT;
struct in6_addr ipv6prefix = IN6ADDR_ANY_INIT;
struct in6_addr pd = IN6ADDR_ANY_INIT;
int offset = -1;
int psidlen = -1;
int psid = -1;
uint16_t psid16 = 0;
const char *dmr = NULL;
const char *br = NULL;
for (char *rule = strdup(argv[i]); *rule; ) {
char *value;
int intval;
int idx = getsubopt(&rule, token, &value);
errno = 0;
if (idx == OPT_TYPE) {
lw4o6 = (value && !strcmp(value, "lw4o6"));
} else if (idx == OPT_FMR) {
fmr = true;
} else if (idx == OPT_EALEN && (intval = strtoul(value, NULL, 0)) <= 48 && !errno) {
ealen = intval;
} else if (idx == OPT_PREFIX4LEN && (intval = strtoul(value, NULL, 0)) <= 32 && !errno) {
prefix4len = intval;
} else if (idx == OPT_PREFIX6LEN && (intval = strtoul(value, NULL, 0)) <= 128 && !errno) {
prefix6len = intval;
} else if (idx == OPT_IPV4PREFIX && inet_pton(AF_INET, value, &ipv4prefix) == 1) {
// dummy
} else if (idx == OPT_IPV6PREFIX && inet_pton(AF_INET6, value, &ipv6prefix) == 1) {
// dummy
} else if (idx == OPT_PD && inet_pton(AF_INET6, value, &pd) == 1) {
// dummy
} else if (idx == OPT_OFFSET && (intval = strtoul(value, NULL, 0)) <= 16 && !errno) {
offset = intval;
} else if (idx == OPT_PSIDLEN && (intval = strtoul(value, NULL, 0)) <= 16 && !errno) {
psidlen = intval;
} else if (idx == OPT_PDLEN && (intval = strtoul(value, NULL, 0)) <= 128 && !errno) {
pdlen = intval;
} else if (idx == OPT_PSID && (intval = strtoul(value, NULL, 0)) <= 65535 && !errno) {
psid = intval;
} else if (idx == OPT_DMR) {
dmr = value;
} else if (idx == OPT_BR) {
br = value;
} else {
if (idx == -1 || idx >= OPT_MAX)
fprintf(stderr, "Skipped invalid option: %s\n", value);
else
fprintf(stderr, "Skipped invalid value %s for option %s\n",
value, token[idx]);
}
}
if (offset < 0)
offset = (lw4o6) ? 0 : (legacy) ? 4 : 6;
// LW4over6 doesn't have an EALEN and has no psid-autodetect
if (lw4o6) {
if (psidlen < 0)
psidlen = 0;
ealen = psidlen;
}
// Find PD
if (pdlen < 0) {
struct blob_attr *c;
unsigned rem;
blobmsg_for_each_attr(c, dump, rem) {
struct blob_attr *tb[IFACE_ATTR_MAX];
blobmsg_parse(iface_attrs, IFACE_ATTR_MAX, tb, blobmsg_data(c), blobmsg_data_len(c));
if (!tb[IFACE_ATTR_INTERFACE] || (strcmp(argv[1], "*") && strcmp(argv[1],
blobmsg_get_string(tb[IFACE_ATTR_INTERFACE]))))
continue;
match_prefix(&pdlen, &pd, tb[IFACE_ATTR_PREFIX], &ipv6prefix, prefix6len, lw4o6);
if (lw4o6)
match_prefix(&pdlen, &pd, tb[IFACE_ATTR_ADDRESS], &ipv6prefix, prefix6len, lw4o6);
if (pdlen >= 0) {
iface = blobmsg_get_string(tb[IFACE_ATTR_INTERFACE]);
break;
}
}
}
if (ealen < 0 && pdlen >= 0)
ealen = pdlen - prefix6len;
if (psidlen <= 0) {
psidlen = ealen - (32 - prefix4len);
if (psidlen < 0)
psidlen = 0;
psid = -1;
}
if (prefix4len < 0 || prefix6len < 0 || ealen < 0 || psidlen > 16 || ealen < psidlen) {
fprintf(stderr, "Skipping invalid or incomplete rule: %s\n", argv[i]);
status = 1;
continue;
}
if (psid < 0 && psidlen >= 0 && pdlen >= 0) {
bmemcpys64(&psid16, &pd, prefix6len + ealen - psidlen, psidlen);
psid = be16_to_cpu(psid16);
}
if (psidlen > 0) {
psid = psid >> (16 - psidlen);
psid16 = cpu_to_be16(psid);
psid = psid << (16 - psidlen);
}
if (pdlen >= 0 || ealen == psidlen) {
bmemcpys64(&ipv4addr, &pd, prefix6len, ealen - psidlen);
ipv4addr.s_addr = htonl(ntohl(ipv4addr.s_addr) >> prefix4len);
bmemcpy(&ipv4addr, &ipv4prefix, prefix4len);
if (prefix4len + ealen < 32)
addr4len = prefix4len + ealen;
}
if (pdlen < 0 && !fmr) {
fprintf(stderr, "Skipping non-FMR without matching PD: %s\n", argv[i]);
status = 1;
continue;
} else if (pdlen >= 0) {
size_t v4offset = (legacy) ? 9 : 10;
memcpy(&ipv6addr.s6_addr[v4offset], &ipv4addr, 4);
memcpy(&ipv6addr.s6_addr[v4offset + 4], &psid16, 2);
bmemcpy(&ipv6addr, &pd, pdlen);
}
++rulecnt;
char ipv4addrbuf[INET_ADDRSTRLEN];
char ipv4prefixbuf[INET_ADDRSTRLEN];
char ipv6prefixbuf[INET6_ADDRSTRLEN];
char ipv6addrbuf[INET6_ADDRSTRLEN];
char pdbuf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET, &ipv4addr, ipv4addrbuf, sizeof(ipv4addrbuf));
inet_ntop(AF_INET, &ipv4prefix, ipv4prefixbuf, sizeof(ipv4prefixbuf));
inet_ntop(AF_INET6, &ipv6prefix, ipv6prefixbuf, sizeof(ipv6prefixbuf));
inet_ntop(AF_INET6, &ipv6addr, ipv6addrbuf, sizeof(ipv6addrbuf));
inet_ntop(AF_INET6, &pd, pdbuf, sizeof(pdbuf));
printf("RULE_%d_FMR=%d\n", rulecnt, fmr);
printf("RULE_%d_EALEN=%d\n", rulecnt, ealen);
printf("RULE_%d_PSIDLEN=%d\n", rulecnt, psidlen);
printf("RULE_%d_OFFSET=%d\n", rulecnt, offset);
printf("RULE_%d_PREFIX4LEN=%d\n", rulecnt, prefix4len);
printf("RULE_%d_PREFIX6LEN=%d\n", rulecnt, prefix6len);
printf("RULE_%d_IPV4PREFIX=%s\n", rulecnt, ipv4prefixbuf);
printf("RULE_%d_IPV6PREFIX=%s\n", rulecnt, ipv6prefixbuf);
if (pdlen >= 0) {
printf("RULE_%d_IPV6PD=%s\n", rulecnt, pdbuf);
printf("RULE_%d_PD6LEN=%d\n", rulecnt, pdlen);
printf("RULE_%d_PD6IFACE=%s\n", rulecnt, iface);
printf("RULE_%d_IPV6ADDR=%s\n", rulecnt, ipv6addrbuf);
printf("RULE_BMR=%d\n", rulecnt);
}
if (ipv4addr.s_addr) {
printf("RULE_%d_IPV4ADDR=%s\n", rulecnt, ipv4addrbuf);
printf("RULE_%d_ADDR4LEN=%d\n", rulecnt, addr4len);
}
if (psidlen > 0 && psid >= 0) {
printf("RULE_%d_PORTSETS='", rulecnt);
for (int k = (offset) ? 1 : 0; k < (1 << offset); ++k) {
int start = (k << (16 - offset)) | (psid >> offset);
int end = start + (1 << (16 - offset - psidlen)) - 1;
if (start == 0)
start = 1;
if (start <= end)
printf("%d-%d ", start, end);
}
printf("'\n");
}
if (dmr)
printf("RULE_%d_DMR=%s\n", rulecnt, dmr);
if (br)
printf("RULE_%d_BR=%s\n", rulecnt, br);
}
printf("RULE_COUNT=%d\n", rulecnt);
return status;
}

View File

@@ -0,0 +1,60 @@
#
# Copyright (C) 2012-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:=odhcp6c
PKG_RELEASE:=18
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/odhcp6c.git
PKG_SOURCE_DATE:=2021-07-14
PKG_SOURCE_VERSION:=94adc8bbfa5150d4c2ceb4e05ecd1840dfa3df08
PKG_MIRROR_HASH:=ddc3b203b37d5f82b88f8dc70f0bfc1b34493cbcba6ed81815ccbe250350fe11
PKG_MAINTAINER:=Hans Dedecker <dedeckeh@gmail.com>
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
CMAKE_OPTIONS += \
-DUSE_LIBUBOX=on
ifneq ($(CONFIG_PACKAGE_odhcp6c_ext_cer_id),0)
CMAKE_OPTIONS += -DEXT_CER_ID=$(CONFIG_PACKAGE_odhcp6c_ext_cer_id)
endif
define Package/odhcp6c
SECTION:=net
CATEGORY:=Network
TITLE:=Embedded DHCPv6-client for OpenWrt
DEPENDS:=@IPV6 +libubox
endef
define Package/odhcp6c/config
config PACKAGE_odhcp6c_ext_cer_id
int "CER-ID Extension ID (0 = disabled)"
depends on PACKAGE_odhcp6c
default 0
endef
define Package/odhcp6c/conffiles
/etc/odhcp6c.user
/etc/odhcp6c.user.d/
endef
define Package/odhcp6c/install
$(INSTALL_DIR) $(1)/usr/sbin/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/odhcp6c $(1)/usr/sbin/
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/dhcpv6.sh $(1)/lib/netifd/proto/dhcpv6.sh
$(INSTALL_BIN) ./files/dhcpv6.script $(1)/lib/netifd/
$(INSTALL_DIR) $(1)/etc/odhcp6c.user.d/
$(INSTALL_CONF) ./files/odhcp6c.user $(1)/etc/
endef
$(eval $(call BuildPackage,odhcp6c))

View File

@@ -0,0 +1,244 @@
#!/bin/sh
[ -z "$2" ] && echo "Error: should be run by odhcpc6c" && exit 1
. /lib/functions.sh
. /lib/netifd/netifd-proto.sh
setup_interface () {
local device="$1"
local prefsig=""
local addrsig=""
# Apply IPv6 / ND configuration
HOPLIMIT=$(cat /proc/sys/net/ipv6/conf/$device/hop_limit)
[ -n "$RA_HOPLIMIT" -a -n "$HOPLIMIT" ] && [ "$RA_HOPLIMIT" -gt "$HOPLIMIT" ] && echo "$RA_HOPLIMIT" > /proc/sys/net/ipv6/conf/$device/hop_limit
[ -n "$RA_MTU" ] && [ "$RA_MTU" -ge 1280 ] && echo "$RA_MTU" > /proc/sys/net/ipv6/conf/$device/mtu 2>/dev/null
[ -n "$RA_REACHABLE" ] && [ "$RA_REACHABLE" -gt 0 ] && echo "$RA_REACHABLE" > /proc/sys/net/ipv6/neigh/$device/base_reachable_time_ms
[ -n "$RA_RETRANSMIT" ] && [ "$RA_RETRANSMIT" -gt 0 ] && echo "$RA_RETRANSMIT" > /proc/sys/net/ipv6/neigh/$device/retrans_time_ms
proto_init_update "*" 1
# Merge RA-DNS
for radns in $RA_DNS; do
local duplicate=0
for dns in $RDNSS; do
[ "$radns" = "$dns" ] && duplicate=1
done
[ "$duplicate" = 0 ] && RDNSS="$RDNSS $radns"
done
for dns in $RDNSS; do
proto_add_dns_server "$dns"
done
for radomain in $RA_DOMAINS; do
local duplicate=0
for domain in $DOMAINS; do
[ "$radomain" = "$domain" ] && duplicate=1
done
[ "$duplicate" = 0 ] && DOMAINS="$DOMAINS $radomain"
done
for domain in $DOMAINS; do
proto_add_dns_search "$domain"
done
for prefix in $PREFIXES; do
proto_add_ipv6_prefix "$prefix"
prefsig="$prefsig ${prefix%%,*}"
local entry="${prefix#*/}"
entry="${entry#*,}"
entry="${entry#*,}"
local valid="${entry%%,*}"
if [ -z "$RA_ADDRESSES" -a -z "$RA_ROUTES" -a \
-z "$RA_DNS" -a "$FAKE_ROUTES" = 1 ]; then
RA_ROUTES="::/0,$SERVER,$valid,4096"
fi
done
for prefix in $USERPREFIX; do
proto_add_ipv6_prefix "$prefix"
done
# Merge addresses
for entry in $RA_ADDRESSES; do
local duplicate=0
local addr="${entry%%/*}"
for dentry in $ADDRESSES; do
local daddr="${dentry%%/*}"
[ "$addr" = "$daddr" ] && duplicate=1
done
[ "$duplicate" = "0" ] && ADDRESSES="$ADDRESSES $entry"
done
for entry in $ADDRESSES; do
local addr="${entry%%/*}"
entry="${entry#*/}"
local mask="${entry%%,*}"
entry="${entry#*,}"
local preferred="${entry%%,*}"
entry="${entry#*,}"
local valid="${entry%%,*}"
proto_add_ipv6_address "$addr" "$mask" "$preferred" "$valid" 1
addrsig="$addrsig $addr/$mask"
if [ -z "$RA_ADDRESSES" -a -z "$RA_ROUTES" -a \
-z "$RA_DNS" -a "$FAKE_ROUTES" = 1 ]; then
RA_ROUTES="::/0,$SERVER,$valid,4096"
fi
# RFC 7278
if [ "$mask" -eq 64 -a -z "$PREFIXES" -a -n "$EXTENDPREFIX" ]; then
proto_add_ipv6_prefix "$addr/$mask,$preferred,$valid"
local raroutes=""
for route in $RA_ROUTES; do
local prefix="${route%%/*}"
local entry="${route#*/}"
local pmask="${entry%%,*}"
entry="${entry#*,}"
local gw="${entry%%,*}"
[ -z "$gw" -a "$mask" = "$pmask" ] && {
case "$addr" in
"${prefix%*::}"*) continue;;
esac
}
raroutes="$raroutes $route"
done
RA_ROUTES="$raroutes"
fi
done
for entry in $RA_ROUTES; do
local duplicate=$NOSOURCEFILTER
local addr="${entry%%/*}"
entry="${entry#*/}"
local mask="${entry%%,*}"
entry="${entry#*,}"
local gw="${entry%%,*}"
entry="${entry#*,}"
local valid="${entry%%,*}"
entry="${entry#*,}"
local metric="${entry%%,*}"
for xentry in $RA_ROUTES; do
local xprefix="${xentry%%,*}"
xentry="${xentry#*,}"
local xgw="${xentry%%,*}"
[ -n "$gw" -a -z "$xgw" -a "$addr/$mask" = "$xprefix" ] && duplicate=1
done
if [ -z "$gw" -o "$duplicate" = 1 ]; then
proto_add_ipv6_route "$addr" "$mask" "$gw" "$metric" "$valid"
else
for prefix in $PREFIXES $ADDRESSES; do
local paddr="${prefix%%,*}"
proto_add_ipv6_route "$addr" "$mask" "$gw" "$metric" "$valid" "$paddr"
done
fi
done
proto_add_data
[ -n "$CER" ] && json_add_string cer "$CER"
[ -n "$PASSTHRU" ] && json_add_string passthru "$PASSTHRU"
[ -n "$ZONE" ] && json_add_string zone "$ZONE"
proto_close_data
proto_send_update "$INTERFACE"
MAPTYPE=""
MAPRULE=""
if [ -n "$MAPE" -a -f /lib/netifd/proto/map.sh ]; then
MAPTYPE="map-e"
MAPRULE="$MAPE"
elif [ -n "$MAPT" -a -f /lib/netifd/proto/map.sh -a -f /proc/net/nat46/control ]; then
MAPTYPE="map-t"
MAPRULE="$MAPT"
elif [ -n "$LW4O6" -a -f /lib/netifd/proto/map.sh ]; then
MAPTYPE="lw4o6"
MAPRULE="$LW4O6"
fi
[ -n "$ZONE" ] || ZONE=$(fw3 -q network $INTERFACE 2>/dev/null)
if [ "$IFACE_MAP" != 0 -a -n "$MAPTYPE" -a -n "$MAPRULE" ]; then
[ -z "$IFACE_MAP" -o "$IFACE_MAP" = 1 ] && IFACE_MAP=${INTERFACE}_4
json_init
json_add_string name "$IFACE_MAP"
json_add_string ifname "@$INTERFACE"
json_add_string proto map
json_add_string type "$MAPTYPE"
json_add_string _prefsig "$prefsig"
[ "$MAPTYPE" = lw4o6 ] && json_add_string _addrsig "$addrsig"
json_add_string rule "$MAPRULE"
json_add_string tunlink "$INTERFACE"
[ -n "$ZONE_MAP" ] || ZONE_MAP=$ZONE
[ -n "$ZONE_MAP" ] && json_add_string zone "$ZONE_MAP"
[ -n "$ENCAPLIMIT_MAP" ] && json_add_string encaplimit "$ENCAPLIMIT_MAP"
[ -n "$IFACE_MAP_DELEGATE" ] && json_add_boolean delegate "$IFACE_MAP_DELEGATE"
json_close_object
ubus call network add_dynamic "$(json_dump)"
elif [ -n "$AFTR" -a "$IFACE_DSLITE" != 0 -a -f /lib/netifd/proto/dslite.sh ]; then
[ -z "$IFACE_DSLITE" -o "$IFACE_DSLITE" = 1 ] && IFACE_DSLITE=${INTERFACE}_4
json_init
json_add_string name "$IFACE_DSLITE"
json_add_string ifname "@$INTERFACE"
json_add_string proto "dslite"
json_add_string peeraddr "$AFTR"
json_add_string tunlink "$INTERFACE"
[ -n "$ZONE_DSLITE" ] || ZONE_DSLITE=$ZONE
[ -n "$ZONE_DSLITE" ] && json_add_string zone "$ZONE_DSLITE"
[ -n "$ENCAPLIMIT_DSLITE" ] && json_add_string encaplimit "$ENCAPLIMIT_DSLITE"
[ -n "$IFACE_DSLITE_DELEGATE" ] && json_add_boolean delegate "$IFACE_DSLITE_DELEGATE"
json_close_object
ubus call network add_dynamic "$(json_dump)"
elif [ "$IFACE_464XLAT" != 0 -a -f /lib/netifd/proto/464xlat.sh ]; then
[ -z "$IFACE_464XLAT" -o "$IFACE_464XLAT" = 1 ] && IFACE_464XLAT=${INTERFACE}_4
json_init
json_add_string name "$IFACE_464XLAT"
json_add_string ifname "@$INTERFACE"
json_add_string proto "464xlat"
json_add_string tunlink "$INTERFACE"
json_add_string _addrsig "$addrsig"
[ -n "$ZONE_464XLAT" ] || ZONE_464XLAT=$ZONE
[ -n "$ZONE_464XLAT" ] && json_add_string zone "$ZONE_464XLAT"
[ -n "$IFACE_464XLAT_DELEGATE" ] && json_add_boolean delegate "$IFACE_464XLAT_DELEGATE"
json_close_object
ubus call network add_dynamic "$(json_dump)"
fi
# TODO: $SNTP_IP $SIP_IP $SNTP_FQDN $SIP_DOMAIN
}
teardown_interface() {
proto_init_update "*" 0
proto_send_update "$INTERFACE"
}
case "$2" in
bound)
teardown_interface "$1"
setup_interface "$1"
;;
informed|updated|rebound)
setup_interface "$1"
;;
ra-updated)
[ -n "$ADDRESSES$RA_ADDRESSES$PREFIXES$USERPREFIX" ] && setup_interface "$1"
;;
started|stopped|unbound)
teardown_interface "$1"
;;
esac
# user rules
[ -f /etc/odhcp6c.user ] && . /etc/odhcp6c.user "$@"
for f in /etc/odhcp6c.user.d/*; do
[ -f "$f" ] && (. "$f" "$@")
done
exit 0

View File

@@ -0,0 +1,137 @@
#!/bin/sh
. /lib/functions.sh
. ../netifd-proto.sh
init_proto "$@"
proto_dhcpv6_init_config() {
renew_handler=1
proto_config_add_string 'reqaddress:or("try","force","none")'
proto_config_add_string 'reqprefix:or("auto","no",range(0, 64))'
proto_config_add_string clientid
proto_config_add_string 'reqopts:list(uinteger)'
proto_config_add_string 'defaultreqopts:bool'
proto_config_add_string 'noslaaconly:bool'
proto_config_add_string 'forceprefix:bool'
proto_config_add_string 'extendprefix:bool'
proto_config_add_string 'norelease:bool'
proto_config_add_string 'noserverunicast:bool'
proto_config_add_string 'noclientfqdn:bool'
proto_config_add_string 'noacceptreconfig:bool'
proto_config_add_array 'ip6prefix:list(ip6addr)'
proto_config_add_string iface_dslite
proto_config_add_string zone_dslite
proto_config_add_string encaplimit_dslite
proto_config_add_string iface_map
proto_config_add_string zone_map
proto_config_add_string encaplimit_map
proto_config_add_string iface_464xlat
proto_config_add_string zone_464xlat
proto_config_add_string zone
proto_config_add_string 'ifaceid:ip6addr'
proto_config_add_string "userclass"
proto_config_add_string "vendorclass"
proto_config_add_array "sendopts:list(string)"
proto_config_add_boolean delegate
proto_config_add_int "soltimeout"
proto_config_add_boolean fakeroutes
proto_config_add_boolean sourcefilter
proto_config_add_boolean keep_ra_dnslifetime
proto_config_add_int "ra_holdoff"
}
proto_dhcpv6_add_prefix() {
append "$3" "$1"
}
proto_dhcpv6_add_sendopts() {
[ -n "$1" ] && append "$3" "-x$1"
}
proto_dhcpv6_setup() {
local config="$1"
local iface="$2"
local reqaddress reqprefix clientid reqopts defaultreqopts noslaaconly forceprefix extendprefix norelease noserverunicast noclientfqdn noacceptreconfig ip6prefix ip6prefixes iface_dslite iface_map iface_464xlat ifaceid userclass vendorclass sendopts delegate zone_dslite zone_map zone_464xlat zone encaplimit_dslite encaplimit_map soltimeout fakeroutes sourcefilter keep_ra_dnslifetime ra_holdoff
json_get_vars reqaddress reqprefix clientid reqopts defaultreqopts noslaaconly forceprefix extendprefix norelease noserverunicast noclientfqdn noacceptreconfig iface_dslite iface_map iface_464xlat ifaceid userclass vendorclass delegate zone_dslite zone_map zone_464xlat zone encaplimit_dslite encaplimit_map soltimeout fakeroutes sourcefilter keep_ra_dnslifetime ra_holdoff
json_for_each_item proto_dhcpv6_add_prefix ip6prefix ip6prefixes
# Configure
local opts=""
[ -n "$reqaddress" ] && append opts "-N$reqaddress"
[ -z "$reqprefix" -o "$reqprefix" = "auto" ] && reqprefix=0
[ "$reqprefix" != "no" ] && append opts "-P$reqprefix"
[ -n "$clientid" ] && append opts "-c$clientid"
[ "$defaultreqopts" = "0" ] && append opts "-R"
[ "$noslaaconly" = "1" ] && append opts "-S"
[ "$forceprefix" = "1" ] && append opts "-F"
[ "$norelease" = "1" ] && append opts "-k"
[ "$noserverunicast" = "1" ] && append opts "-U"
[ "$noclientfqdn" = "1" ] && append opts "-f"
[ "$noacceptreconfig" = "1" ] && append opts "-a"
[ -n "$ifaceid" ] && append opts "-i$ifaceid"
[ -n "$vendorclass" ] && append opts "-V$vendorclass"
[ -n "$userclass" ] && append opts "-u$userclass"
[ "$keep_ra_dnslifetime" = "1" ] && append opts "-L"
[ -n "$ra_holdoff" ] && append opts "-m$ra_holdoff"
local opt
for opt in $reqopts; do
append opts "-r$opt"
done
json_for_each_item proto_dhcpv6_add_sendopts sendopts opts
append opts "-t${soltimeout:-120}"
[ -n "$ip6prefixes" ] && proto_export "USERPREFIX=$ip6prefixes"
[ -n "$iface_dslite" ] && proto_export "IFACE_DSLITE=$iface_dslite"
[ -n "$iface_map" ] && proto_export "IFACE_MAP=$iface_map"
[ -n "$iface_464xlat" ] && proto_export "IFACE_464XLAT=$iface_464xlat"
[ "$delegate" = "0" ] && proto_export "IFACE_DSLITE_DELEGATE=0"
[ "$delegate" = "0" ] && proto_export "IFACE_MAP_DELEGATE=0"
[ -n "$zone_dslite" ] && proto_export "ZONE_DSLITE=$zone_dslite"
[ -n "$zone_map" ] && proto_export "ZONE_MAP=$zone_map"
[ -n "$zone_464xlat" ] && proto_export "ZONE_464XLAT=$zone_464xlat"
[ -n "$zone" ] && proto_export "ZONE=$zone"
[ -n "$encaplimit_dslite" ] && proto_export "ENCAPLIMIT_DSLITE=$encaplimit_dslite"
[ -n "$encaplimit_map" ] && proto_export "ENCAPLIMIT_MAP=$encaplimit_map"
[ "$fakeroutes" != "0" ] && proto_export "FAKE_ROUTES=1"
[ "$sourcefilter" = "0" ] && proto_export "NOSOURCEFILTER=1"
[ "$extendprefix" = "1" ] && proto_export "EXTENDPREFIX=1"
proto_export "INTERFACE=$config"
proto_run_command "$config" odhcp6c \
-s /lib/netifd/dhcpv6.script \
$opts $iface
}
proto_dhcpv6_renew() {
local interface="$1"
# SIGUSR1 forces odhcp6c to renew its lease
local sigusr1="$(kill -l SIGUSR1)"
[ -n "$sigusr1" ] && proto_kill_command "$interface" $sigusr1
}
proto_dhcpv6_teardown() {
local interface="$1"
proto_kill_command "$interface"
}
add_protocol dhcpv6

View File

@@ -0,0 +1 @@
# This script is sourced by odhcp6c's dhcpv6.script at every DHCPv6 event.

View File

@@ -0,0 +1,61 @@
#
# Copyright (C) 2009-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:=thc-ipv6
PKG_VERSION:=2.7
PKG_RELEASE:=1
PKG_LICENSE:=GPL-3.0
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=@GITHUB/vanhauser-thc/THC-Archive/master/Tools
PKG_HASH:=440a3ae98b57100c397ec4f8634468dbbb0c3b48788c6b74af2a597a90544a96
PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
include $(INCLUDE_DIR)/package.mk
THC_APPLETS := \
address6 alive6 covert_send6 covert_send6d denial6 detect-new-ip6 \
detect_sniffer6 dnsdict6 dnsrevenum6 dos-new-ip6 \
dump_router6 exploit6 fake_advertise6 fake_dhcps6 fake_dns6d \
fake_dnsupdate6 fake_mipv6 fake_mld26 fake_mld6 fake_mldrouter6 \
fake_router26 fake_router6 fake_solicitate6 flood_advertise6 \
flood_dhcpc6 flood_mld26 flood_mld6 flood_mldrouter6 flood_router26 \
flood_router6 flood_solicitate6 fragmentation6 fuzz_ip6 fuzz_dhcpc6 \
fuzz_dhcps6 implementation6 implementation6d inverse_lookup6 \
kill_router6 ndpexhaust6 node_query6 parasite6 passive_discovery6 \
randicmp6 redir6 rsmurf6 sendpees6 sendpeesmp6 smurf6 thcping6 \
toobig6 trace6
THC_DEPENDS_dnsdict6 := +libpthread
THC_DEPENDS_thcping6 := +librt
define BuildTool
define Package/thc-ipv6-$(subst _,-,$(1))
TITLE:=THC-IPv6 $(1) utility
SECTION:=net
CATEGORY:=Network
DEPENDS:=+libpcap $(THC_DEPENDS_$(1))
URL:=https://github.com/vanhauser-thc/thc-ipv6
SUBMENU:=THC-IPv6 attack and analyzing toolkit
endef
define Package/thc-ipv6-$(subst _,-,$(1))/description
This package contains the $(1) utility of the THC-IPv6 toolkit.
endef
define Package/thc-ipv6-$(subst _,-,$(1))/install
$(INSTALL_DIR) $$(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/$(1) $$(1)/usr/sbin/$(1)
endef
$$(eval $$(call BuildPackage,thc-ipv6-$(subst _,-,$(1))))
endef
$(foreach a,$(THC_APPLETS),$(eval $(call BuildTool,$(a))))

View File

@@ -0,0 +1,12 @@
diff -urN thc-ipv6-2.7/Makefile thc-ipv6-2.7.new/Makefile
--- thc-ipv6-2.7/Makefile 2014-12-27 05:05:30.000000000 -0800
+++ thc-ipv6-2.7.new/Makefile 2017-02-04 20:55:51.679898101 -0800
@@ -3,7 +3,7 @@
CC=gcc
#CFLAGS=-g
-CFLAGS=-O2
+CFLAGS?=-O2
CFLAGS+=$(if $(HAVE_SSL),-D_HAVE_SSL,)
LDFLAGS+=-lpcap $(if $(HAVE_SSL),-lssl -lcrypto,)
PROGRAMS=parasite6 dos-new-ip6 detect-new-ip6 fake_router6 fake_advertise6 fake_solicitate6 fake_mld6 fake_mld26 fake_mldrouter6 flood_mldrouter6 fake_mipv6 redir6 smurf6 alive6 toobig6 rsmurf6 implementation6 implementation6d sendpees6 sendpeesmp6 randicmp6 fuzz_ip6 flood_mld6 flood_mld26 flood_router6 flood_advertise6 flood_solicitate6 trace6 exploit6 denial6 fake_dhcps6 flood_dhcpc6 fake_dns6d fragmentation6 kill_router6 fake_dnsupdate6 ndpexhaust6 detect_sniffer6 dump_router6 fake_router26 flood_router26 passive_discovery6 dnsrevenum6 inverse_lookup6 node_query6 address6 covert_send6 covert_send6d inject_alive6 firewall6 ndpexhaust26 fake_pim6 thcsyn6 redirsniff6 flood_redir6 four2six dump_dhcp6 fuzz_dhcps6 flood_rs6 fuzz_dhcpc6

View File

@@ -0,0 +1,9 @@
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
# Comment out if openssl-dev is not present
-HAVE_SSL=yes
+#HAVE_SSL=yes
CC=gcc
#CFLAGS=-g

View File

@@ -0,0 +1,199 @@
#
# 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
PKG_NAME:=dnsmasq
PKG_UPSTREAM_VERSION:=2.86
PKG_VERSION:=$(subst test,~~test,$(subst rc,~rc,$(PKG_UPSTREAM_VERSION)))
PKG_RELEASE:=$(AUTORELEASE)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_UPSTREAM_VERSION).tar.xz
PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq
PKG_HASH:=28d52cfc9e2004ac4f85274f52b32e1647b4dbc9761b82e7de1e41c49907eb08
PKG_LICENSE:=GPL-2.0
PKG_LICENSE_FILES:=COPYING
PKG_CPE_ID:=cpe:/a:thekelleys:dnsmasq
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_UPSTREAM_VERSION)
PKG_INSTALL:=1
PKG_BUILD_PARALLEL:=1
PKG_ASLR_PIE_REGULAR:=1
PKG_CONFIG_DEPENDS:= CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dhcp \
CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dhcpv6 \
CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dnssec \
CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_auth \
CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_ipset \
CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_conntrack \
CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_noid \
CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_broken_rtc \
CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_tftp
include $(INCLUDE_DIR)/package.mk
define Package/dnsmasq/Default
SECTION:=net
CATEGORY:=Base system
TITLE:=DNS and DHCP server
URL:=http://www.thekelleys.org.uk/dnsmasq/
DEPENDS:=+libubus
USERID:=dnsmasq=453:dnsmasq=453
endef
define Package/dnsmasq
$(call Package/dnsmasq/Default)
VARIANT:=nodhcpv6
endef
define Package/dnsmasq-dhcpv6
$(call Package/dnsmasq/Default)
TITLE += (with DHCPv6 support)
DEPENDS+=@IPV6
VARIANT:=dhcpv6
PROVIDES:=dnsmasq
endef
define Package/dnsmasq-full
$(call Package/dnsmasq/Default)
TITLE += (with DNSSEC, DHCPv6, Auth DNS, IPset, Conntrack, NO_ID enabled by default)
DEPENDS+=+PACKAGE_dnsmasq_full_dnssec:libnettle \
+PACKAGE_dnsmasq_full_ipset:kmod-ipt-ipset \
+PACKAGE_dnsmasq_full_conntrack:libnetfilter-conntrack
VARIANT:=full
PROVIDES:=dnsmasq
endef
define Package/dnsmasq/description
It is intended to provide coupled DNS and DHCP service to a LAN.
endef
define Package/dnsmasq-dhcpv6/description
$(call Package/dnsmasq/description)
This is a variant with DHCPv6 support
endef
define Package/dnsmasq-full/description
$(call Package/dnsmasq/description)
This is a fully configurable variant with DHCPv4, DHCPv6, DNSSEC, Authoritative DNS
and IPset, Conntrack support & NO_ID enabled by default.
endef
define Package/dnsmasq/conffiles
/etc/config/dhcp
/etc/dnsmasq.conf
/etc/dnsmasq.d/
endef
define Package/dnsmasq-full/config
if PACKAGE_dnsmasq-full
config PACKAGE_dnsmasq_full_dhcp
bool "Build with DHCP support."
default y
config PACKAGE_dnsmasq_full_dhcpv6
bool "Build with DHCPv6 support."
depends on IPV6 && PACKAGE_dnsmasq_full_dhcp
default y
config PACKAGE_dnsmasq_full_dnssec
bool "Build with DNSSEC support."
default y
config PACKAGE_dnsmasq_full_auth
bool "Build with the facility to act as an authoritative DNS server."
default y
config PACKAGE_dnsmasq_full_ipset
bool "Build with IPset support."
default y
config PACKAGE_dnsmasq_full_conntrack
bool "Build with Conntrack support."
default y
config PACKAGE_dnsmasq_full_noid
bool "Build with NO_ID. (hide *.bind pseudo domain)"
default y
config PACKAGE_dnsmasq_full_broken_rtc
bool "Build with HAVE_BROKEN_RTC."
default n
config PACKAGE_dnsmasq_full_tftp
bool "Build with TFTP server support."
default y
endif
endef
Package/dnsmasq-dhcpv6/conffiles = $(Package/dnsmasq/conffiles)
Package/dnsmasq-full/conffiles = $(Package/dnsmasq/conffiles)
TARGET_CFLAGS += -flto
TARGET_LDFLAGS += -flto=jobserver
COPTS = -DHAVE_UBUS -DHAVE_POLL_H \
$(if $(CONFIG_IPV6),,-DNO_IPV6)
ifeq ($(BUILD_VARIANT),nodhcpv6)
COPTS += -DNO_DHCP6
endif
ifeq ($(BUILD_VARIANT),full)
COPTS += $(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dhcp),,-DNO_DHCP) \
$(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dhcpv6),,-DNO_DHCP6) \
$(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dnssec),-DHAVE_DNSSEC) \
$(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_auth),,-DNO_AUTH) \
$(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_ipset),,-DNO_IPSET) \
$(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_conntrack),-DHAVE_CONNTRACK,) \
$(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_noid),-DNO_ID,) \
$(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_broken_rtc),-DHAVE_BROKEN_RTC) \
$(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_tftp),,-DNO_TFTP)
COPTS += $(if $(CONFIG_LIBNETTLE_MINI),-DNO_GMP,)
else
COPTS += -DNO_AUTH -DNO_IPSET -DNO_ID
endif
MAKE_FLAGS := \
$(TARGET_CONFIGURE_OPTS) \
CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
LDFLAGS="$(TARGET_LDFLAGS)" \
COPTS="$(COPTS)" \
PREFIX="/usr"
define Package/dnsmasq/install
$(INSTALL_DIR) $(1)/usr/sbin
$(CP) $(PKG_INSTALL_DIR)/usr/sbin/dnsmasq $(1)/usr/sbin/
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/dhcp.conf $(1)/etc/config/dhcp
$(INSTALL_CONF) ./files/dnsmasq.conf $(1)/etc/dnsmasq.conf
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/dnsmasq.init $(1)/etc/init.d/dnsmasq
$(INSTALL_DIR) $(1)/etc/hotplug.d/dhcp
$(INSTALL_DIR) $(1)/etc/hotplug.d/neigh
$(INSTALL_DIR) $(1)/etc/hotplug.d/ntp
$(INSTALL_DIR) $(1)/etc/hotplug.d/tftp
$(INSTALL_DATA) ./files/dnsmasqsec.hotplug $(1)/etc/hotplug.d/ntp/25-dnsmasqsec
$(INSTALL_DIR) $(1)/usr/share/dnsmasq
$(INSTALL_CONF) ./files/dhcpbogushostname.conf $(1)/usr/share/dnsmasq/
$(INSTALL_CONF) ./files/rfc6761.conf $(1)/usr/share/dnsmasq/
$(INSTALL_DIR) $(1)/usr/lib/dnsmasq
$(INSTALL_BIN) ./files/dhcp-script.sh $(1)/usr/lib/dnsmasq/dhcp-script.sh
$(INSTALL_DIR) $(1)/usr/share/acl.d
$(INSTALL_DATA) ./files/dnsmasq_acl.json $(1)/usr/share/acl.d/
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_BIN) ./files/50-dnsmasq-migrate-resolv-conf-auto.sh $(1)/etc/uci-defaults
endef
Package/dnsmasq-dhcpv6/install = $(Package/dnsmasq/install)
define Package/dnsmasq-full/install
$(call Package/dnsmasq/install,$(1))
ifneq ($(CONFIG_PACKAGE_dnsmasq_full_dnssec),)
$(INSTALL_DIR) $(1)/usr/share/dnsmasq
$(INSTALL_CONF) $(PKG_BUILD_DIR)/trust-anchors.conf $(1)/usr/share/dnsmasq
endif
endef
$(eval $(call BuildPackage,dnsmasq))
$(eval $(call BuildPackage,dnsmasq-dhcpv6))
$(eval $(call BuildPackage,dnsmasq-full))

View File

@@ -0,0 +1,8 @@
#!/bin/sh
[ "$(uci get dhcp.@dnsmasq[0].resolvfile)" = "/tmp/resolv.conf.auto" ] && {
uci set dhcp.@dnsmasq[0].resolvfile="/tmp/resolv.conf.d/resolv.conf.auto"
uci commit dhcp
}
exit 0

View File

@@ -0,0 +1,53 @@
#!/bin/sh
[ -f "$USER_DHCPSCRIPT" ] && . "$USER_DHCPSCRIPT" "$@"
. /usr/share/libubox/jshn.sh
json_init
json_add_array env
hotplugobj=""
case "$1" in
add | del | old | arp-add | arp-del)
json_add_string "" "MACADDR=$2"
json_add_string "" "IPADDR=$3"
;;
esac
case "$1" in
add)
json_add_string "" "ACTION=add"
json_add_string "" "HOSTNAME=$4"
hotplugobj="dhcp"
;;
del)
json_add_string "" "ACTION=remove"
json_add_string "" "HOSTNAME=$4"
hotplugobj="dhcp"
;;
old)
json_add_string "" "ACTION=update"
json_add_string "" "HOSTNAME=$4"
hotplugobj="dhcp"
;;
arp-add)
json_add_string "" "ACTION=add"
hotplugobj="neigh"
;;
arp-del)
json_add_string "" "ACTION=remove"
hotplugobj="neigh"
;;
tftp)
json_add_string "" "ACTION=add"
json_add_string "" "TFTP_SIZE=$2"
json_add_string "" "TFTP_ADDR=$3"
json_add_string "" "TFTP_PATH=$4"
hotplugobj="tftp"
;;
esac
json_close_array env
[ -n "$hotplugobj" ] && ubus call hotplug.${hotplugobj} call "$(json_dump)"

View File

@@ -0,0 +1,33 @@
config dnsmasq
option domainneeded 1
option boguspriv 1
option filterwin2k 0 # enable for dial on demand
option localise_queries 1
option rebind_protection 1 # disable if upstream must serve RFC1918 addresses
option rebind_localhost 1 # enable for RBL checking and similar services
#list rebind_domain example.lan # whitelist RFC1918 responses for domains
option local '/lan/'
option domain 'lan'
option expandhosts 1
option nonegcache 0
option authoritative 1
option readethers 1
option leasefile '/tmp/dhcp.leases'
option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
#list server '/mycompany.local/1.2.3.4'
option nonwildcard 1 # bind to & keep track of interfaces
#list interface br-lan
#list notinterface lo
#list bogusnxdomain '64.94.110.11'
option localservice 1 # disable to allow DNS requests from non-local subnets
option ednspacket_max 1232
config dhcp lan
option interface lan
option start 100
option limit 150
option leasetime 12h
config dhcp wan
option interface wan
option ignore 1

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